最新WEB 前端模块化方案完全总结(1),web开发学习培训

❤️ 谢谢支持

喜欢的话别忘了 关注、点赞哦~。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

前端校招面试题精编解析大全

console.log(name, m1.getName())

}

return { show }

})

定义 index.js

(function(){

// 配置模块的路径

require.config({

paths: {

m1: ‘./m1’

m2: ‘./m2’

}

})

require([‘m2’], function(m2){

m2.show()

})

})()

然后就可以看到执行结果了。

AMD是依赖前置的,即不管你用没用到,只要你设置了依赖就会去加载,不是按需加载的。

上面的代码在浏览器里运行,会先后发生这些事情:

  • 它首先根据指定的require.js加载require.js

  • 加载完成后,require.js会在所有的 script 标签里寻找 data-main 属性指定的路径文件作为下一个将要加载的脚本,在这里,就是./index.js

  • 开始加载./index.js,加载后,解析并执行它,如果发现它有其他依赖,那么先加载所有的依赖(递归)并完成后,再执行./index.js里面 require 的回调函数;

页面就绪后,我们可以在渲染后的 DOM 树中看到<head>标签里多了几个<script>元素,require.js正是通过这些标签来加载相应的 AMD 模块文件的。

CMD

相比 AMD,CMD 也同样是异步加载,AMD 是依赖前置,CMD 是就近加载,按需加载的。主要产物就是sea.js

SeaJS 最初以就近加载以及支持加载 CSS 等特点吸引了很多用户,并提出了 CMD 规范。但在 RequireJS 也支持这些特性之后渐渐淡出,虽然 SeaJS 没有明显的缺点,但统一标准未尝不是一件好事。

sea.js核心思想与 AMD 高度类似,通过 define 定义模块,require 加载模块,如下:

定义 m1

define(function (require, exports, module) {

var msg = ‘m1’

function foo() {

console.log(msg);

}

module.exports = {

foo

}

})

定义 m2

define(function (require, exports, module) {

var msg = ‘m2’

function bar() {

console.log(msg);

}

module.exports = bar

})

定义 m3

define(function (require, exports, module) {

var msg = ‘m3’

function fun() {

console.log(msg);

}

exports.fun = fun

})

定义 m4

define(function (require, exports, module) {

var msg = ‘m4’

var m2 = require(‘./m2’)

m2()

require.async(‘./m3’, function(m3){

m3.fun()

})

function func () {

console.log(msg)

}

exports.func = func

})

定义 index.js

define(function (require, exports, module) {

var m1 = require(‘./m1’)

m1.foo()

var m4 = require(‘./m4’)

m4.func()

})

UMD


鉴于存在 CommonJS、AMD 等不同的模块系统,为了让代码能够同时支持它们,社区提出了一种统一模块定义(Universal Module Definition,UMD)来解决不兼容的问题。所以,UMD 其实不是什么标准,可以看成是 IIFE amd + cjs 的兼容版。也就是一个 js 文件,可以用 script 标签引用加载,用 RequireJS 加载,也可以在 node 当成 CommonJS 模块加载。

一个常见的 UMD 模块声明实际上是一个立即执行函数表达式。模块的主体在一个工厂方法里面,其返回值作为模块最终暴露的对象。例如下面的模块暴露了一个构造函数 Time:

(function (global, factory) {

typeof exports === ‘object’ && typeof module !== ‘undefined’ ? module.exports = factory() :

typeof define === ‘function’ && define.amd ? define(factory) :

global.Time = factory();

}(this, function () {

// 模块工厂方法开始

‘use strict’;

var _private = ‘’;

function Time(param) {

this._date = new Date(param);

}

return Time;

// 模块工厂方法结束

}));

以上原理其实很简单,因为通常如果一个变量在取右值时未定义,会发生引用错误(Reference Error),例如:

// 标识符 an_undefined_token 不在当前作用域链上

console.log(an_undefined_token);

// 会报如下错误

// Uncaught ReferenceError: an_undefined_token is not defined

但是 typeof 运算符有所不同,typeof an_undefined_token 并不会报任何错,而是输出 undefined。利用 JS 的这个运算符,我们可以在脚本加载后立即执行模块头部代码,利用特性检测来判断环境中存在的是哪种模块系统。所以:

  • 如果 exports 是个对象,而且 module 也存在,那么运行工程函数,拿到其返回值,然后像任何一个 NodeJS 模块一样,将返回值赋给 module.exports。

  • 如果 define 是个函数,而且 define 上面存在 amd 属性(RequireJS 的特性,表示这是一个 AMD 加载器),那么使用 define 函数将模块工厂函数加到队列里。

  • 如果上面两个特性检测都失败,就在全局对象上面挂载该模块的返回值。

UMD 模块试图对当前最流行的那些脚本加载器(例如 RequireJS)提供足够好的兼容性。很多情况下,它使用 AMD 为基础,并对特殊情况处理以提供 CommonJS 兼容性。

ESM,ECMAScript 模块系统(ES6)


所谓 ESM,即 ECMAScript2015 Module,也就是 ES6 中的模块化。工作原理是模块文件只加载、执行一次。ES6 自带模块化,从语言的标准上实现了模块化,使用 export 导出,import导入。

let a = 10

let b = 20

let c = ‘aaa’

export function myFun(){}

export default foo(){}

export default 默认导出,不管是否导出其他,这个后面跟的东西一定会被导出,而且只能写一个默认导出。

ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。现在许多打包工具利用 ES6 的特点, 按需提取代码, 打出的包更加精简,如下:

//按需加载依赖

import { stat, exists, readFile } from ‘fs’;

//暴露接口

export default obj; // 默认对外接口

export var foo = ‘str’; // 名称为foo的对外接口

总结


综上可以看见,IIFE 的方便会让其长期存在,而 AMD 在浏览器端还是霸主阶段,在服务端 ES6 标准化取代 CJS 是一种趋势,但 CJS 标准的庞大类库会让它暂时难以取代。

| 标准 | 变量问题 | 依赖 | 动态加载 | 静态分析 |

| :-: | :-: | :-: | :-: | :-: |

| iife | ✔ | ✘ | ✘ | ✘ |

| amd | ✔ | ✔ | ✔ | ✘ |

| cmd | ✔ | ✔ | ✔ | ✘ |

| cjs | ✔ | ✔ | ✘ | ✘ |

| es6 | ✔ | ✔ | ✘ | ✔ |

以上就是关于模块的所有的总结。

最后

小编综合了阿里的面试题做了一份前端面试题PDF文档,里面有面试题的详细解析

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

虽只说了一个公司的面试,但我们可以知道大厂关注的东西并举一反三,通过一个知识点延伸到另一个知识点,这是我们要掌握的学习方法,小伙伴们在这篇有学到的请评论点赞转发告诉小编哦,谢谢大家的支持!

频】](https://bbs.csdn.net/topics/618166371)**

虽只说了一个公司的面试,但我们可以知道大厂关注的东西并举一反三,通过一个知识点延伸到另一个知识点,这是我们要掌握的学习方法,小伙伴们在这篇有学到的请评论点赞转发告诉小编哦,谢谢大家的支持!

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值