课程名称:web前端架构师
课程章节:第12周 第6章
主讲老师:张轩
课程内容:模块化的发展历史
模块化
模块化的优点
可维护性
可复用性
开始
使用 backbone.js 的方法
<script src="spec/support/jquery.js"></script>
<script src="spec/support/underscore.js"></script>
<script src="spec/support/backbone.js"></script>
<script src="backbone.localStorage.js"></script>
<script src="todos.js"></script></script>
全局变量 + 命名空间(IIFE)
IIFE 自执行函数,创建一个封闭的作用域,赋值给一个全局变量,这种方式在之前很常用,比如 jquery就是通过这种方式实现的。
var namesCollection = (function() {
// private members
var objects = [];
// Public Method
function addObject(object) {
objects.push(object);
printMessage(object);
}
// Private Method
function printMessage(object) {
console.log("Object successfully added:", object);
}
// public members, exposed with return statement
return {
addName: addObject,
};
})();
namesCollection.addName('viking')
现在很多库打包的时候也会输出 iife 格式,但书写的的时候会采用 esm 方式,然后通过 webpack、rollup 等打包工具输出各种格式
缺点
- 依赖全局变量,污染全局作用域,不安全
- 依赖约定命名空间来避免冲突,可靠性不高
- 需要手动管理依赖并控制执行顺序,容易出错
- 需要在最终上线前手动合并所有用到的模块
Commonjs
nodejs 使用的就是这种格式,但是commonjs采用的是同步加载文件,不适合浏览器使用
const bar = require('./bar')
module.exports = function() {
}
AMD
- 采用异步方式加载模块
- 仅仅需要在全局环境定义 require 与 define,不需要其他的全局变量
- 通过文件路径或模块自己声明的模块名定位模块
- 提供了打包工具自动分析依赖并合并
- 配合特定的 AMD 加载器使用,RequireJS
- 同时还诞生了很多类似的模块标准 CMD
define(function(require) {
// 通过相对路径获取依赖模块
const bar = require('./bar')
// 模块产出
return function () {
}
})
缺点就是需要额外引入其他库
ESM
- 引入和暴露的方式更加多样
- 支持复杂的静态分析。可以很好的配合其他工具 tree-shaking去除无用代码
<script type="module" src="/main.js"></script>
// 通过相对路径获取依赖模块 默认.js不可省略,我们使用打包工具帮我们处理就可以省略了
import bar from './bar.js'
// 模块产出
export default function () {
}
目前绝大多数浏览器都是支持ES Modules
ESM的基本特性
- ESM 自动采用严格模式,忽略 ‘use strict’
- 每个 ES Module 都是运行在单独的私有作用域中
- ESM通过 CORS 的方式请求外部js模块的
- ESM的script标签会延迟脚本执行
打包工具
使用打包工具的好处
-
可以使用es6+新特性。很多浏览器不能直接支持es+新特性的语法,需要使用babel编译后,复制粘贴到代码中。
部署上线需要手动压缩代码。过去上生产环境需要手动将代码压缩后,复制粘贴到文件中,非常容易出错。工程化就无须担心这些会出错。 -
想要使用Less/Sass/PostCss增强css编程性,但是运行环境不能直接支持。比如写css代码需要写很多浏览器兼容的代码,过去要么手动写兼容代码(开发代码会变多),要么使用编译器编译后复制粘贴到代码中,工程化就无须考虑兼容性问题,提高了编码质量,
-
无须再担心开发过程跨域问题。开发调试接口有跨域问题,需要将代码发给后端或在本地起一个后端服务才能看到效果,使用工程化代理,就无须担心跨域问题 总之工程化解决了工作过程中很多重复操作的问题,提高了开发效率和编码质量,降低了开发成本。
webpack
webpack 我们都比较熟悉,应该是目前使用最多的模块打包工具。
- 通过各种 Loader 处理各种各样的静态资源
- 通过各种插件 Plugins 对整体文件进行一些处理。
- Code splitting 将公共模块进行提取。
- 提供一个 webpack-dev-server,进行本地开发。
- 支持 HMR 模块热替换。
缺点就是 webpack 打包后会有多余的代码,打包速度比较慢
rollup
Rollup 设计之初就是面向 ES module ** 的,构建出结构扁平,性能出众**的类库。
ES module 的规则
- import只能作为模块顶层的语句出现,不能出现在 function 里面或是 if 里面。
- ES import的模块名只能是字符串常量。
- 不管 import 的语句出现的位置在哪里,在模块初始化的时候所有的 import 都必须已经导入完成。
rollup 从最开始就支持 tree-shaking ,并且打包后的文件没有多余的代码,目前很多库都是使用 rollup 进行打包,比如 vue、react, vite 创建的项目 在生产环境使用的也是 rollup 进行打包