背景
面试经常被问到模块化,类似:谈谈模块化的历程?AMD和CMD的区别?然而自己脑子里却没有一个完整的知识体系,回答得支支吾吾,真是难受,因此下定决心把这一块知识给整理一遍。
模块化
模块化是什么?
含义:将一个复杂的程序依据一定的规则(规范)封装成几个块(文件),并进行组合在一起的内部数据/实现是私有的,只是想外部暴露一些接口(方法)与外部的模块通信
进化史
- 简单封装:Namespace 模式
- 匿名函数:IIFE 模式(立即执行函数)
- 模块模式:引入依赖
- 现代模块化的基石
为什么要模块化?
- web 的发展飞速,不仅仅局限于静态页面,而向着应用发展,功能越来越丰富
- 代码复杂度越来越高
- 对代码进行解耦的需要
- 减少文件大小,节约 Http 请求时间
模块化的好处
- 避免命名冲突(减少命名空间污染)
- 更好的分离,按需加载
- 更高复用性
- 高可复用性
实现方式
页面引入<script>
加载资源
进而引发的问题
- 请求过多
- 依赖模糊
- 难以维护
模块化规范
CommonJS
规范
说明
- 每个文件都可当做一个模块
- 在服务器:模块的加载是运行时同步加载的
- 在浏览器:模块需要提前编译打包处理
- javascript.ruanyifeng.com/nodejs/modu…
基本语法
- 暴露模块
module.exports = value
exports.xxx = value
- 引入模块
require(xxx)
- 第三方模块:xxx 为模块名
- 自定义模块:xxx 为模块文件路径
实现
服务器端实现
- Node.js
- nodejs.cn/
浏览器端实现
- Browserify
- 称为 CommonJS 的浏览器端的打包工具
- browserify.org/
AMD
规范
说明
- Asynchronous Module Definition 异步模块加载机制
- github.com/amdjs/amdjs…
- 专门用于浏览器端,模块的加载是异步的
基本语法
定义暴露模块
- 定义没有依赖的模块
define(function(){
return 模块
})
复制代码
- 定义有依赖的模块
define(['module1', 'module2'], function(m1, m2) {
return 模块
})
复制代码
引入使用模块
require(['module1', 'module2'], function (m1, m2) {
使用 m1/m2
})
复制代码
实现(浏览器)
- Require.js
- www.requirejs-cn.cn/
CMD
规范
说明
- Common Module Definition (通用模块定义)
- 专门用于浏览器端,模块的加载是异步的
- 模块使用时才会加载执行
基本语法
定义暴露模块
- 定义没有依赖的模块
define(function(require, exports, module) {
exports.xxx = value
// or
module.exports = value
})
复制代码
- 定义有依赖的模块
define(function(require, exports, module) {
// 引入依赖模块(同步语法)
var module2 = require('./module2')
// 引入依赖模块(异步)
require.async('./module3', function() {
// 暴露模块
exports.xxx = value
})
})
复制代码
- 引入使用模块
define(function(require) {
var m1 = require('./module1')
var m4 = require('./module4')
m1.show()
m4.show()
})
复制代码
实现(浏览器端)
- Sea.js
- seajs.github.io/seajs/docs/
ES2015
规范
说明
- es6.ruanyifeng.com/
- 依赖模块需要编译打包处理
基本语法
- 导出模块:
export
- 导入模块:
import
实现(浏览器端)
- 使用 Babel 将 ES6 的代码编译为 ES5 代码
- 使用 Browserify 编译打包 js
UMD
规范
说明
- Universal Module Definition
- 兼容多个运行环境的统一模块化规范
- github.com/umdjs/umd
实现
- Babel 打包
脑图
文档:JS 模块化知识汇总.mindmap
链接:note.youdao.com/noteshare?i…
总结
- AMD 推崇依赖模块前置,CMD 推崇依赖模块就近
require
是对模块的复制,import
是对模块的引用- AMD/CMD/CommomJS 模块化规范是运行时加载,ES6 模块化规范是编译时输出接口
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END