javascript 的打包工具

2022 年了,js 还是那个 js。我曾几度嫌弃 js,但最后还是拥抱 js。它的确不完美,但哪个完美呢?既然和 js 打交道,就避免不了要使用 打包工具

为什么需要打包工具

打包工具从来都 不是必要 ,后端(nodejs) 几乎可以不使用 ,前端, 几乎不可以不用

一、合并

在上古时期,打包工具解决的一个主要问题是,把多个 js 文件合并成一个 js 文件。因为 js 原本没有 import 或 require,你不可能把整个应用、网站的代码写在一个文件里,既不美观也不方面。

而现在,有了 require,有了 import,我们依然需要打包工具。因为项目不是一个人写的,你不知道你的合作伙伴用的是 require 还是 import,而它俩是不兼容的。这时,打包工具的目的就是,使它们兼容。

就算项目是一个人在做,难道不会使用 react 或 vue 或……。很难确保自己的代码和依赖中的代码兼容。

名词解释:依赖。如果你的项目中使用了 react,那么就可以说“你的项目依赖 react”,这时是动词。更广泛的说法是“react 是你项目的依赖”,这时作名词。

就算你的项目没有任何依赖,打包工具往往也是必要的,因为还有下面几个理由。

二、编译

使用“编译”这个词,我认为是很 不恰当 的,但没有更合适的词。

ES6 的发布也有年头了,但支持度依然堪忧,老的浏览器就不支持。这时候就需要 babel 编译一下—— 把新的 js 代码变成老的 js 代码

另外,ts(typescript)这几年风生水起,但是即使是新的浏览器,也不支持。也需要编译成 js 才可以—— 把 ts 代码变成 js 代码

还有一种情况,就是在 js 文件中, 引入其他类型的文件 (大多只用于前端)。比如 css。ES6 是新版的 js;ts 是带类型的 js;而 css,除了它的名字里也有“s”,其他和 js 还真没什么关系。它俩(css 和 js)就像在一个办公室里的同事,要合作办一件事;但职责不同,理念也不一样,长相更不一样。所以我头回听说在 js 里引入 css 时就很不解。

但其实打包工具允许我们在 js 中引入 css 的目的很简单。可以这样理解,从前的从前,办公大楼的人都是按工作类型分的楼层。这样,可能写代码的在一楼,测试在二楼,UI 在三楼;或者写代码的在办公室南头,测试在办公室北头。后来发现,按项目分座位更方便一点,同一个项目的成员应该坐一起。

而程序的源代码以前则是把 css 放在一个文件夹,把 js 放在另一个文件夹(这样做不是没有原因的,这里不做讨论)。现在则一般把一个组件或一个功能的文件放在一起。如果你用过 react 那一定知道 jsx,它其实是把 html 引入 js 里。

有两款流行的打包工具,webpack 和 rollup,它们在没有安装任何 loader、plugin 的情况下,几乎都没有编译功能。转化 es6,webpack 要安装 babel loader,rollup 要 babel plugin;转化 ts,webpack 要 ts loader;rollup 要 ts plugin……

三、其他

有的老板害怕自己的代码被别人剽窃,于是希望给代码“加密”。程序员就使用“ 混淆 ”, 把代码变得更加混乱 ,反正人类看不懂就是了。说得好像原来别人看得懂。

或者,发现程序加载比较慢,于是给 代码洗澡

  • 把永远不会被运行到的代码删掉
  • 把变量的名字变短,比如原来你有个变量叫 shaoshiBrother,打包之后就变成了 sb 或 s,也有可能叫 a
  • 把多余的空格、空行删掉

或者,有的同仁很严谨,他希望自己的代码遵循一定的规则,这样就能防 bug 于未然。于是就有 各种各样的 lint ,在打包的时候,就可以自动检查出不规范的东西,甚至 bug。

或者,……

还有一个,用现在流行的话来说,就很荒诞了。打包工具在打包之余,还往往提供“ 服务器 ”的功能。在打好包之后,它会告诉你访问 localhost:3000 可以看看打包的结果。实在讲,服务器的确不属于打包工具的功能。这违背了“只做一件事”原则。

打包工具盘点

首先,如果你认为有某一款工具,比其他的都棒,那也许应该放下偏见。毕竟没有不好的打包工具,只有没人用的打包工具。

grunt 与 gulp

这哥们俩,名字就很像,而且年龄相仿、工作相似,就连误解也是如出一辙。 它俩不是打包工具 ,但任何讨论打包工具的文章,这老哥俩从不缺席,也不能缺席。

在从前,没有打包工具。老哥俩的工作是“自动化”。比如把大象放进冰箱分三步:把冰箱门打开,把大象放进去,把冰箱门关上。以前你要一步一步办,但在这老哥俩的帮助下,你只要一步:告诉 grunt 或 gulp“帮我把大象放进冰箱”。当然,你得事先告诉老哥俩,是怎么放进去的(把步骤写在一个文件里)。也就是说,你只要做一次,以后都是老哥俩来干。

这样看, grunt 和 gulp 其实是很通用、但没有特定目的的自动化工具 。而打包,只不过是多才多艺的老哥俩的一个功能而已。通用是老哥俩的优点也是缺点。grunt 和 gulp 要求开发者“对打包流程有一定的了解”。否则你告诉老哥俩“嘿师傅,帮我打包”,老哥俩会说“打...?咳,咳咳咳,打谁?”

有意思的是,年轻时,grunt 和 gulp 互相竞争、共同进步。年老被别人品头论足时,一提就是 Grunt 和 Gulp,俩G,gg。

用马冬梅梗来嘲讽 grunt 和 gulp 实在是不礼貌,但太好玩了。老哥俩虽然风光不再,但不是因为理念或技术的落后,而是格局变了。不可否认的说,编程对程序员的要求在降低。各种工具、库,上来就是“开箱即用”,动不动就号称“小白入门”、“女朋友也能学会”,这不是在歧视女性吗 [狗头][狗头]。

不推荐。

vite

我没用过 vite。但最近 vite 实在是太火了,我连夜看了 两遍 文档。和老哥俩相比,是另一个极端。没错,“开箱即用”说的就是它。对于新入门的选手,特别是新的 vue 写手,我比较推荐(毕竟 vue 和 vite 是表兄弟)。因为新手得把更多精力用于“如何写代码”上。

vite 的亮点就在于开箱即用,你不用研究“如何把大象放入冰箱”,vite 知道该怎么做。

另外,“快”是 vite 另一个亮点。rollup、esbuild、预编译……十八般武艺,令我眼花缭乱。以前打包需要十几分钟,现在你只需要 xx 毫秒。(后面有两位,也这么说)

但。如果说 gg 老哥俩的工作车间比较简陋,而且各种导线外露。那 vite 的工作车间就高级多了,也简洁多了,但简洁的白墙之下埋了多少条导线,实在是令人难以捉摸。万一哪天有只虫子顺着导线爬进墙里,在里面盖起了二层洋楼导致短路。这么大的白墙,你知道它的洋楼盖在哪里?

不出问题笑嘻嘻,一有问题 mmp。梗真是越老越有味。

只推荐新手使用。

snowpack

如果说 vite 是 vue 的表兄弟,那 snowpack 就是 react 的远方表弟。它天生支持 react。

除了对 react 的开箱即用,在“快”方面,snowpack 可真是(从某种意义上说)天下第一。因为(别笑)它,,,,有时候,,,,,不打包。

因为现代浏览器已经支持 import 了。snowpack 说“既然浏览器已经支持 import 了,那我就不打包了,费那个劲干啥?”尽管你的依赖中肯定有使用 require 的,但 snowpack 说“那我只 把 require 转化成 import 不就行了”。弯道超车,尽管野,那也是条路子。

但。就我前几个月,使用 snowpack 的体验来说,snowpack 的功能还不健全,还有明显的 bug。

但但。snowpack 的前途还是明亮的,就像前两年 es6 必转 es5;这两年,不转好像也行了。

不推荐在重要的生产项目中使用。

parcel

要论表兄弟,parcel 可就晃来晃去坐不住了,立刻站起身来、甩起浑厚的嗓子嚷道“老子 跟谁都是表兄弟 ”。(尽管别人不承认)

你甚至不用手动安装 vue 或 react 或任何依赖:当你的代码中出现一个未安装的依赖时,parcel 会帮你安装。甚至当你需要 babel、typescript、less、sass 时,它也能自动检测并自动安装。简单,粗暴,和谁都是表兄弟,真不是盖的。

但。这也意味着 parcel 的白墙之下,埋了更多导线。而且住了好多家虫子,已经繁衍生息了好几代了。我曾经只在两个小项目中用过 parcel,开始时真爽,收场时……

不推荐。

esbuild

parcel 在“跟谁是表兄弟”方面天下无敌,而 esbuild 则是在 打包效率 方面独领风骚(snowpack 这种野路子不算)。这得益于 esbuild 是一款使用 go 语言开发的工具。go 语言够快,所以 esbuild 也快。

如果说,打包工具们在自己家院子里比武,esbuild 就像是请了外援。

但请外援怎么了,只要能为我所用,都一样。

但。我没用过 esbuild……对不起!!所以我就不多说了,凭直觉来说, 很推荐 (新手不推荐)。因为 vite 底层也使用了 esbuild,也就是说 vite 车间的白墙后面,其实有 esbuild 在干活。

当然 vite 的白墙后面还有一位:rollup。

rollup

rollup 是我接触最晚的打包工具(不算没用过的 esbuild),也是我现在的主力选手,真是相见恨晚啊。以前我看别人的“打包工具盘点”,就以为 rollup 是“发布 npm 包时,用 rollup;开发应用时,用 webpack”。但其实只需要安装一个 rollup-plugin-serve,rollup 开发应用也很棒。

特点:

  • rollup 不是开箱即用,所以不存在“白墙之下”的问题,但 对开发者要求也更高 (直接把新手拒之门外)
  • 但你不需要像 gg 老哥俩那样,要描述怎么打包,只需要弄清楚“你需要哪些依赖”就行了
  • 打包效率适中
  • 成熟、稳定

非常推荐成熟的程序员使用 ,不推荐新手使用。

webpack

来了来了,说起打包工具,不说谁也不能不说 webpack。webpack 大约的确是名声最响也最臭的了。它也是我接触最早的打包工具,我主观的观点是:

  • 虽然臃肿,但不难用
  • 速度不快,但可接受
  • 功能多
  • bug 少
  • 非开箱即用

webpack 可能是这几款里,最慢的打包工具了。但说真的,没到“不可忍受”的地步。我前几天试用了一下 webpack5,虽然依然很慢[笑],但还可以。项目真到了打个包需要十几分钟,难道不应该分分模块吗,打包需要十几分钟,用户就算 100M 宽带,不也得加载个,,,,,,,好多秒。

这么多用户使用,迭代了 5 个大版本,这不是没有理由的。之前有一个因素,我没考虑,那就是“用户数量”。一个开发工具,它再好,别人都不用,就你一个人用,在团队里肯定是不行的。所以 webpack 另外一个大优点是: 吃得开 。再说一句,没有不好的工具,只有没人用的工具。

推荐成熟的程序员使用 ,不推荐新手使用。

编辑于 2022-01-13 16:39