模块化概述
- 最主流的代码组织方式
- 模块化只是思想
模块化的演进过程
-
基于文件划分
缺点:污染全局作用域、命名冲突、无法管理模块依赖关系、完全依靠约定
-
命名空间方式
将模块包装成一个全局对象、减小命名冲突、仍然没有私有空间、变量可以被修改、依赖关系无法管理
-
使用立即执行函数为模块提供私有空间
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZHDKGgoH-1651320618136)(模块化开发/image-20220412214127261.png)]
使用立即执行函数的参数管理模块依赖
例如使用jQuery模块
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bQLQJXok-1651320618139)(模块化开发/image-20220412214436295.png)]
以上方式不受代码控制,只能通过标签引入,容易遗忘或删除引入,每个人的依赖实现都有细微的差异
模块化规范的出现
通过代码自动加载模块
CommonJS规范
- 一个文件就是一个模块
- 每个模块都有单独的作用域
- 通过module.exports导出成员
- 通过require函数载入模块
浏览器端使用会有一些问题,CommonJS是以同步模式加载模块,node会在启动时加载模块,执行过程中不加载模块,只会使用到模块,所以没问题,浏览器端会产生大量同步请求,效率低下
AMD(Asynchronous Module Definition)异步模块定义规范
浏览器端规范
异步模块库 Require.js 实现了AMD规范,本身是一个模块加载器
AMD规范约定每一个模块都需要使用define定义
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uqGxoByz-1651320618140)(模块化开发/image-20220413091154791.png)]
define函数接收三参数
第一个参数:模块的名字
第二个参数:数组 用来此模块的依赖项
第三个参数:函数 函数的参数与依赖项对应
require模块还提供了一个require函数用于加载一个模块
与define函数类似,但是只用来加载模块,内部会创建一个script标签
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gMSOxtwe-1651320618142)(模块化开发/image-20220413100754457.png)]
AMD使用起来相对复杂
模块JS文件请求频分
淘宝官方提供了一个Sea.js+CMD规范
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DoIRha4d-1651320618143)(模块化开发/image-20220415191727854.png)]
模块化标准规范
模块化的最佳实践
nodejs 遵循Commonjs
浏览器端遵循ES Modules
ES modules
基本特性
通过给script添加 type = module 的属性,就可以以ES Module的标准执行其中的JS代码
type=module自动使用严格模式(use strict)
严格模式
- 不能在全局直接使用this
每个module都是运行在单独的私有作用域中
ESM 是通过CORS的方式请求外部JS模块的
ESM的script标签会延迟执行脚本,会等待页面渲染完成后在执行(defer)
ES Module 导出
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G1fvl4eP-1651320618145)(模块化开发/image-20220416102250493.png)]
Brower Sync 启动一个具有热更新能力的web server
export 导出的是成员的引用,node是将值赋值个成员
模块外部不能修改成员的值
ES Modules导入用法
动态导入模块
import('./module.js').then(function(module){
console.log(module)
})
import title,{name,age} from './module.js'
console.log(title,name,age)
ES Module 导出导入成员
// 所有导入成员直接作为导出成员
export{foo,bar} from './module.js'
console.log(foo,bar)
ES Modules浏览器环境Polyfill
IE不支持浏览器标签
polyfill可以在浏览器中直接支持ES Module的绝大多数的特性,模块名ES Module Loader
ES Modules in Node.js-支持情况
node --experimental-modules index.mjs
ES Modules in Node.js -与 CommonJS 交互
// commonjs.js
exports.foo = 'commonjs exports value'
// exports就是module.exports的别名
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MGPAElbS-1651320618146)(模块化开发/image-20220416172610744.png)]
ES Modules in Node.js-与CommonJS的差异
通过nodemon --experimental-modules esm.mjs
启动模块,当模块修改之后自动加载文件
ES Modules in Node.js-新版本进一步支持
// 通过给package.json文件中添加一个type字段,项目下所有js文件默认是es modules
{"type":"module"}
对于commonjs规范将扩展名改为cjs就可以了
ES Modules in Node.js-Babel兼容方案
新版本进一步支持
// 通过给package.json文件中添加一个type字段,项目下所有js文件默认是es modules
{"type":"module"}
对于commonjs规范将扩展名改为cjs就可以了