1.1 Javascript模块化历史
模块(modules)是什么?
模块简单来说就是一组重用的代码,被提取到不同的文件
from package import function
package main
import (
"fmt"
)
模块的优点
- 可维护性
- 可复用性
ES6 之前没有模块的 年代
// 使用 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>
全局变量 + 命名空间(namespace)
var namesCollection = (function() {
return {
addName(name) {
console.log(name)
}
}
})()
namesCollection.addName('zhipeng')
缺点
- 依赖全局变量,污染全局作用域,不安全
- 依赖约定命名空间来避免冲突,可靠性不高
- 需要手动管理依赖并控制执行顺序,容易出错
- 需要在最终上线前手动合并所有用到的模块
Common.js
const bar = require('./bar')
module.exports = function() {}
缺点
- 无法在浏览器使用
AMD - (Asynchronous module definition)
- 采用异步方式加载模块
- 仅仅需要在全局环境定义 require 与 define,不需要其他的全局变量
- 通过文件路径或模块自己声明的模块名定位模块
- 提供了打包工具自动分析依赖并合并
- 配合特定的 AMD 加载器使用,RequireJS
- 同时还诞生了很多类似的模块标准 CMD
define(function(require) {
// 通过相对路径获取依赖模块
const bar = require('./bar')
// 模块产出
return function () {
}
})
ES6 modules
// 通过相对路径获取依赖模块
import bar from './bar'
// 模块产出
export default function () {
}
- 引入和暴露的方式更加多样
- 支持复杂的静态分析
1.2 打包工具的根本作用
Bundler 是什么?
诞生原因
使用 import export 这种同步加载的方式在大多数浏览器中无法使用,
Bundler - 打包工具
将浏览器不支持的模块进行编译,转换,合并最后生成的代码可以在浏览器端良好的运行的工具。
- Webpack
- Rollup
1.3 Webpack vs Rollup
Webpack
大型 SPA 项目的模块化构建,也就是我们常说的 web 应用。
- 通过各种 Loader 处理各种各样的静态资源
- 通过各种插件 Plugins 对整体文件进行一些处理。
- Code splitting 将公共模块进行提取。
- 提供一个 webpack-dev-server,进行本地开发。
- 支持 HMR 模块热替换。
Rollup
Rollup 设计之初就是面向 ES module ** 的,构建出结构扁平,性能出众**的类库。
ES module 的规则
- import只能作为模块顶层的语句出现,不能出现在 function 里面或是 if 里面。
- ES import的模块名只能是字符串常量。
- 不管 import 的语句出现的位置在哪里,在模块初始化的时候所有的 import 都必须已经导入完成。
使用工具静态分析的过程
- Tree shaking 机制 - 摇树!让死了的叶子掉下来。
- 目的就是将 es modules 打包生产特定的 JS 模块文件,并减小它的体积。
Webpack vs Rollup
通过以上的对比可以得出,构建App应用时,webpack比较合适,如果是类库(纯js项目),rollup更加适合。
Webpack 的优势
- 强大的生态插件
- 面向开发应用的特性支持 HMR,按需加载,公共模块提取
- 简化 Web 开发的环节,图片自动转 base64,资源的缓存(添加 chunkId)
Rollup 的优势
- 构建高性能的 模块文件,这正是类库所需要的。
- 编译出来的代码可读性好,内容更小,执行效率更高。
- 配置比较简单。