本文是开发工具集系列文章之一,其他请点击这里。
本文只包含整体性讨论,具体打包器用法原理请参考后续文章
模块打包器(module bundler),顾名思义就是将各个模块(module)打包到一个或几个文件中,然后在html文件中引入。
在es module中,module是对应script的一个概念,即可以理解为应用中使用到的非全局js。
1 打包器的由来
古时候,我们将自己写的源码和第三方library在html文件中用script标签引入,这种做法随着项目规模的扩大会带来很多问题,主要问题为
- 变量都在全局作用域,容易命名冲突
- 需要处理好文件之间的依赖,代码引入要注意加载顺序
- http请求过多,出现性能问题
- 代码维护复杂
1.1 IIEF
这里我们先试着解决作用域的问题,在es5中除了全局作用域还有函数作用域,那么我们可以将代码拆分到不同函数作用域中,可以使用IIFE结合revealing module,如
var revealed = function(){
var a = [1,2,3];
function abc(){
return (a[0]*a[1])+a[2];
}
return {
name: 'revealed',
abcfn: abc
}
}();
这样一定程度上改善了作用域问题,可以使用gulp等task-runner将不同文件中的代码拼接在一起,但是没解决依赖的问题。
1.2 module loader
我们需要真正的模块才能解决这些问题,虽然后来node.js端出现了commonjs,但是浏览器端并没有对应的语法,因此出现了amd、cmd等module formats,对应requirejs、systemjs等module loader实现了这些规范,浏览器端也就有了自己的模块化,这些module loader可以在js运行时解析依赖关系,并实现了按需加载。
1.3 module bundler
module loader并没有解决http请求数量多的问题,module bundler的出现在前者的基础上将所有模块打包到一个(也可以多个)js文件中,实际在浏览器运行时使用的是打包后的文件。当然如果没有配置好,将所有模块同时放在同一个文件一起加载,也会产生负面效果。
参考
- A 10 minute primer to JavaScript modules, module formats, module loaders and module bundlers
- why webpack
2 打包器的现状
现在的打包器已经是在模块处理方面占据着主流位置,虽然浏览器端已经出现了语法上的模块,模块打包器依然被人们广为使用。
现在可用的打包器很多,这里会选两种使用较广泛的打包器来深入讨论,即webpack和rollup,另外parcel和browserify也有一定的用户量,感兴趣可以自己了解,其中前者使用简单,后者发布较早,npm trends显示如下
3 打包器评测
一个合格的打包器,我们需要利用一些评价指标来评测,以便选择更合适的打包器,并做出最佳实践。这里 我们参考 A health checkup for web build tools。
这里我们分6个维度、若干个小项来对browserify、parcel、rollup、webpack进行评价,分别为
- 代码拆分(Code Splitting)通过将bundle拆分成多个文件,从而是先按需加载。
- 新的worker之间代码拆分,包括Service Workers, Module Workers and Worklets.
- main线程和worker线程之间代码拆分
- 动态引入
- 多个入口之间的重复依赖
- 同一个入口的不同文件之间的重复依赖
- 不同bundle之间导入的变量是不是live binding
- 用于缓存的hash值得生成
- js依赖的asset修改,对应的hash值是否修改
- asset依赖的asset修改,两者对应的hash是否修改,比如css依赖的img
- 对于js之间的引用,应有一个import map避免一个文件修改时所以依赖该文件的文件hash都要改
- hash值可禁用
- 基本的根据内容生成的hash
- 只更改路径不修改内容,hash应一样
- hash值是否是根据最终文件的内容生成
- 如果没有import map,被依赖js修改,对应js的hash应修改
- 模块输入,注意browserify不支持esmodule
- 是否支持commonjs
- 是否支持esmodule
- 是否支持在node_modules引入
- 非js资源处理
- 二进制,比如通过arrayBuffer或url
- css
- 是否支持css模块化(有独立作用域)
- 是否能在js文件中import
- 能否由导入的css获取对应的url
- 自定义类型
- 依赖
- 被引入的非js文件能否有依赖
- js和非js的依赖项要去重
- 入口可以是非js文件么,比如html
- 在html文件中生成资源
- 内联script
- 根据最新生成的bundle更新html中用来引入的script标签
- preload相关asset
- preload js依赖
- 图片,通过data url或者asset url
- Service Workers
- 模块导出格式
- 生成commonjs
- 自定义模块
- es 模块
- 转换
- 使用Brotli压缩
- 图片自动优化
- svg自动优化
- 清理未使用的代码
- 清理动态引入但未使用的代码
- 环境变量等flag
- 压缩js
- 转换js以兼容旧版本
最终成绩我们关注的rollup和webpack很接近,webpack稍稍领先,相比其他两个差距较大。其中rollup在hashing项失分较多,webpack不可以导出es module。
打包器的具体介绍请参考本文开始相关的链接
完结撒花
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!