前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何从广度与深度衡量打包工具的好坏

如何从广度与深度衡量打包工具的好坏

作者头像
公众号@魔术师卡颂
发布2021-04-21 11:31:11
9860
发布2021-04-21 11:31:11
举报
文章被收录于专栏:魔术师卡颂

专注React,学不会你打我!

「代码编译打包」是如今前端工程化中绕不开的一环,这项功能依赖于「打包工具」

最常见、受众最广的打包工具当属webpack

同时,在webpack势力范围之外,存在一些在某些方面很突出的打包工具满足一部分细分领域的需求。

当我们要开发一个新项目,该使用哪种打包工具?怎么衡量打包工具的优劣呢?

本文会从几个纬度来评价一款打包工具优劣。

首先让我们简单了解下市面上常见打包工具的特点:

webpack

基于loaderplugin机制,接入灵活。同时由于有先发优势,有完备的社区储备。

缺点是灵活的配置造成上手成本高,遇到问题不易调试。

rollup

如果说webpack偏向应用打包,那rollup更偏向于库的打包。

其对ESM更好的支持使更好的tree-shaking能力有了原生的底层支持。

parcel

对标webpack的繁杂配置,parcel的的目标是「零配置完成打包」

向开发者屏蔽配置固然利于上手,但是当默认配置无法满足需要时这种优势就会被打破。

browserify

特点是使用CJS标准打包,使一份代码同时在node环境与浏览器环境(打包后)执行。

其中,在浏览器环境中,node的一些核心库(如eventsstreampath...)会被打包成浏览器支持的版本。

缺点:缺少ESM标准的约束,在tree-shaking上存在天生劣势。

vite

基于浏览器原生支持的ESM标准,vitedev环境可以提供极快的预览效果。

同时基于go语言编写的esbuild,使vite的打包速度与以上几个工具有了数量级的差异。

评价打包工具优劣

Google工程师Surma[1]和其他人一起打造了一个评价打包工具优劣的开源项目tooling.report[2]。

该项目按以下5个纬度衡量打包工具优劣:

Code splitting 代码分割

「代码分割」可以在开发者无感知(或者很少感知)的情况下,将代码拆分到不同到包,在运行时按需加载。

这种方式可以显著减少运行时需要下载和执行的JS代码。

「代码分割」包含很多因素:

  • Dynamic import(动态import)

比如webpack会将动态import语法编译为运行时以jsonp形式加载并执行代码。

CJS作为打包标准的browserify不支持ESM,显然更不会支持动态import

  • 是否支持不同上下文

浏览器中除了JS线程,还有worker线程(如service workerweb worker)。

当使用了worker,打包工具是否会为不同上下文打包不同的文件?

JS线程worker之间,workerworker之间之间是否能复用公用代码?

  • 不同chunk是否能复用引用

不同入口是否能将公共的引用抽离出来只实例化一次?这里又分为「单入口应用」「多入口应用」

Hashing 缓存

最理想的用户体验:第一次访问页面时请求静态资源数据,并缓存下来。再次请求时使用缓存数据。

这样能极大加快页面展示时间,减少服务器负荷。

但是缓存有失效/更新问题,如果静态资源已经更新,但是缓存未失效,这是很严重的问题。

当前业界主要解决方式是:静态资源本身不会失效,通过在资源url上增加hash来区分不同版本的资源。

这就为打包工具带来挑战:

一个「非JS资源」使用hash url,当其发生变化,引用他的「JS文件」需要改变引用的hash url,这可能造成该「JS文件」hash url改变,从而造成递归的连锁反应。

如何将这种连锁反应控制在最合理的限度?

webpackhash分为hashcontent hashchunk hash,就是为了以不同粒度的hash控制连锁反应的范围。

Importing modules 模块导入

随着ESM规范普及,越来越多的工具开始支持导出为ESM规范。

但是由于历史原因,很多以库都是以CJS规范导出。

打包工具是否同时支持CJSESM?如何处理依赖文件(node_modules)中CJSESM混用的情况?

Non-JavaScript resources 非JS资源的打包

典型的web应用不仅仅包含JS代码,还包含HTMLCSS图片字体等。

如何在打包工具中处理好这些资源之间的依赖关系?

Output module formats 打包产物的格式

JS有不同宿主环境,浏览器、Nodeworker等。

Node v12之前,Node环境只支持CJS规范。

大部分现代浏览器支持ESM规范。

Web Workers只有在chrome中支持ESM规范。

针对不同宿主环境,需要能打包出不同规范的产物。

Transformations 代码转换

针对不同类型资源,打包工具是否支持代码转换。

我们知道babel可以将JS代码转换为AST,在此基础上完成诸如:

  • ES6ES5
  • 代码压缩

在这一步,打包工具是否能做的更优秀?

比如基于「数据流分析」Dead Code Elimination(移除未使用代码)

是否能支持更多格式?

比如压缩图片、SVG...

总结

基于以上5个纬度,4款打包工具的得分如下:

可以看到,虽然我们时常吐槽webpack配置让人抓狂,但是webpack各方面确实很优秀。

颇有种带头大哥“每手都要抓,每手都要硬”的感觉。

关于每个得分标准的详细解析参考tooling.report官网[3]

参考资料

[1]

Surma: https://github.com/surma

[2]

tooling.report: https://github.com/GoogleChromeLabs/tooling.report

[3]

tooling.report官网: https://bundlers.tooling.report/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-04-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 魔术师卡颂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • webpack
  • rollup
  • parcel
  • browserify
  • vite
  • 评价打包工具优劣
    • Code splitting 代码分割
      • Hashing 缓存
        • Importing modules 模块导入
          • Non-JavaScript resources 非JS资源的打包
            • Output module formats 打包产物的格式
              • Transformations 代码转换
              • 总结
                • 参考资料
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档