前端工程化基石:构建工具,构建工具家族图谱🛠️
前言
“学不动了, 真学不动了!”
“造轮子, 前端就是天天造轮子!”
“别更新了, 我要跟不上了!”
.....
为什么市面上已经有这么多构建工具了,有 esbuild 、webpack 、rollup 等等等,还有源源不断的构建工具出现,重复的造轮子真的有必要吗,我们前端除了造轮子,没有其他事情了吗?在这篇文章开始之前,我们先讨论一个话题 -- 为什么构建工具层出不穷?这是不是无意义的「内卷」。 在推特上,有这么一篇帖子,讨论了重复造轮子的意义,得出了一个结论为了洞察而重新发明,为了影响力而重用,我认同这个观点。
市面上出现了太多的构建工具,大家可能会在各种构建工具中难以抉择,今天我们就来统一的对这些构建工具进行统一分类。
构建工具
什么是构建工具,它负责将开发者编写的模块化代码( JS/TS/CSS/图片 等)及其依赖关系,经过编译、转换、优化、合并等处理,最终输出为浏览器可直接运行的高效静态资源。在早期中,由于项目的体型较小,因此我们手动处理依赖关系,但随着技术的更新迭代,项目的体型也越来越大,因此我们需要自动化的构建工具,帮我们去完成一系列的处理。
类别
在这里我们讨论两类构建工具,第一类是底层构建工具,例如 webpack、rollup 、 esbuild等,第二类是基于这些底层构建的高层封装工具,帮助我们以低配置,甚至零配置的方式进行打包,例如 tsup 、tsdown。
底层构建工具
- 开发语言:
JS - 优点
- 历史积累,生态系统丰富
- 强大的模块处理
- 丰富的插件系统
- 缺点
- 配置复杂,调试成本高
- 大型项目性能瓶颈明显
- 冷启动慢
- 适用于大型复杂
SPA项目,微前端等
- 开发语言:
JS - 优点
- 原生支持
Tree Shaking - 插件系统功能丰富
- 产物体积小
ES Modules打包
- 原生支持
- 缺点
- 不支持
HMR - 对某些类型资源类型,或
cjs模块,需要第三方插件实现
- 不支持
- 不适用于项目应用打包,适用于库模式打包
- 开发语言:
Go - 优点
- 编译速度极快
- 多线程编译
- 零配置开箱即用
- 缺点
- 功能单一
- 插件生态弱
- 不适用于复杂应用
- 开发语言:
Rust - 优点
Webpack生态无缝迁移Rust驱动,冷启动快- 字节跳动开源,文档友好
- 内置
Lightning CSS加速
- 缺点
- 生态较新,插件覆盖不足
- 文档成熟度待提升
- 适用于
Webpack技术债迁移,目前较为成熟的Rust构建方案
- 开发语言:
Rust - 优点:
Webpack团队推出新版开发工具- 深度集成
Next.js
- 缺点
- 插件系统未成熟
- 比较不推荐的打包工具,推出后不温不火,曾公布性能基准测试,声称比
Vite快10倍,遭到 yyx 回怼
- 开发语言:
Rust - 优点
Rust开发,构建速度快- 基于
Oxc工具集合构建 - 未来将作为 Vite 的底层构建工具
- 兼容
Rollup API,兼容Rollup生态
- 缺点
- 目前仅发布 1.0 beta 版本,项目仍在开发中
- 文档不完善
Rolldown 作为构建工具领域的明日之星,正受到开发者社区的万众瞩目。它即将成为 Vite 新一代的底层构建引擎,取代现有的 Esbuild 和 Rollup,而是通过性能跃升补强 Vite 的生产构建能力。
这一变革的期待值之所以高涨,源于 Vite 近年来在《JavaScript 现状调查报告》中的统治级表现:在构建工具满意度、采用率等核心榜单中持续霸榜首位,已成为前端生态最受欢迎的构建解决方案。而 Rolldown 作为 Vite 团队钦定的未来基座,自然承载着开发者对更快、更稳、更强大的构建体验的终极期待。
高层封装工具
底层框架:Esbuild / Rollup。在开发环境中使用 Esbuild,在生产环境中使用 Rollup;在开发阶段依靠 Esbuild 的特性,拥有极快的冷启动速度,而生产环境中则需要较长的打包时间;由于开发和生产环境中使用了两种不同的构建工具,因此可能出现构建产物不一致的结果,导致出现无法预测的错误;由于 Vite 依靠的是浏览器原生的 ESM 特性,在开发时构建大型项目,会出现加载过多的请求情况,导致白屏时间过长。
这也是目前 Vite 最受诟病的三大因素,因此 Vite 团队致力于开发 Rolldown 来解决这三个因素,官网推出基于 Rolldown 驱动的 Vite 目前以名为 rolldown-vite 的独立包提供,大家目前可以使用这个包体验由 Rolldown 驱动的效果。
底层架构:Rspack。与框架无关,支持 React、Vue、Solid、Svelte、Preact 等框架的构建,对标 Vite,致力于提升前端的开发体验。
底层架构:Rspack。专为 JavaScript/TypeScript 库开发设计,可用来打包工具库,组件库等。
底层框架:Rollup。unbuild 是专门为打包 Nuxt、Nitro 和 UnJS 库而创建的,由于 unbuild 的设计最初是有特定的打包对象,因此官方并未生成专门的文档也并未进行宣传,仅有 Readme.md 说明文档,这也是大多数人并未听说过该构建工具的原因。
底层框架:Rolldown。与 unbuild 为同一个作者,也是用来代替 unbuild 的一个工具,因此与 unbuild 类似有特定的打包对象,也并未进行宣传。
底层框架:Esbuild。构建 TypeScript 库的最简单、最快捷的构建工具,也是目前库仓库打包最流行的工具之一。
底层框架:Rolldown。tsdown 是由 Rolldown 团队推出的全新库构建工具,目前正处于积极开发阶段。其核心定位为 基于 Rust 工具链的 TypeScript 库构建解决方案,设计上深度参考 tsup 的功能范式,支持一键式迁移现有 tsup 项目。
作为 Rolldown 生态的官方成员,它与 Vue 框架存在紧密的技术协同—— 可利用 unplugin-vue 插件,对 Vue 组件库的编译与打包。在功能定位上,tsdown 与 obuild 高度趋同,均致力于通过 Rust 驱动实现库构建的极速体验。
关于 rolldown-vite
尤大在五月三十日刚发布了一篇博客,详细的介绍了 rolldown-vite,有兴趣的小伙伴可以阅读一下。
总结:
rolldown-vite已集成了rolldown作为底层构建工具,构建速度显著加快。- 但目前仍处于测试阶段,插件仍存在部分兼容性问题,旨在用户体验,以及发现问题,解决问题。
- 不建议在生产环境使用,可能会存在无法预知的错误。
以下是我自己的测试结果:
vite
rolldown-vite
总的来说,rolldown-vite 的构建速度远快于 vite,但可能由于硬件设施的问题,以及插件的兼容性问题 (部分插件仍需要借助 esbuild,在后续中将 transformWithWsbuild 迁移至 transformWithOxc 应该还会快上不少。) 感观上觉得 rolldown-vite 还是不够快,差距并不明显。
tsdown
现在,让我们以 tsdown 作为构建工具,通过实际动手操作来深入探索它的功能特性。
项目准备
初始化项目,安装依赖
npm init -y
npm i -D tsdown
文件结构
├── dist/ # 构建后自动生成
├── node_modules/ # npm 安装后自动生成
├── src/
│ ├── index.ts # 项目入口文件
│ └── utils.ts # 工具函数
├── package.json
└── tsdown.config.ts # 配置文件
tsdown 配置
// index.ts
export { add, foo } from './utils'
// utils.ts
export const foo = Object.defineProperties(
{
bar: 'bar',
},
{
baz: {
value: 'baz',
enumerable: true,
},
},
)
export function add(a: number, b: number) {
return a + b
}
// tsdown.config.ts
import { defineConfig } from 'tsdown'
export default defineConfig({
// 文件入口,可以指定单一入口(字符串),也可以指定多个入口(数组)
entry: ['./src/index.ts'],
// 输出目录,默认为 dist
outDir: './dist',
// 构建目标,会将代码中的语法进行降级
// 例如当你指定为 es5 时,代码中的箭头函数会被降级为普通函数
target: 'es6',
// 构建格式,esm | cjs | iife,默认为 esm,可以指定一个(字符串),也可以指定多个(数组)
format: 'esm',
// 清理,每次构建之前清理输出目录(默认为 dist)
clean: false,
// 声明文件,项目中必须安装 typescript
dts: true,
// 运行平台,node | browser | neutral
platform: 'neutral',
// 监听模式,检测文件内容发生变化,自动重新打包
watch: false,
// 源码映射
sourcemap: true,
// 树摇,默认开启,没有使用到的函数会被删除,不会打进最终产物中
treeshake: true,
// 拆包,默认关闭,开启后,会拆分出多个文件,每个文件对应一个入口文件
unbundle: false,
// 压缩代码,减少代码体积
minify: true,
// 指定外部依赖,并不会将 external 的包打进最终产物中
external: ['react'],
// 强制将 noExternal 的包打进最终产物中
noExternal: ['vue'],
})
{
"scripts": {
"build": "tsdown",
"dev": "tsdown --watch"
}
}
启动命令后,构建完成后,dist 目录下为最终构建产物,用户就能将该产物进行服务器部署,或者 npm 包发布。
总结
选择构建工具的核心在于契合项目需求。 大型复杂项目可考虑底层工具,以获得丰富的配置选项和功能;小型简单项目则适合高层封装工具,它们开箱即用,能显著降低配置成本。
大家也不妨尝鲜 Rolldown 和 tsdown,它们未来有望成为前端圈的明星项目。欢迎体验并反馈问题,一起帮助项目优化,共建更健壮的工具生态!🚀
构建工具如星辰,各有其独特轨迹。每款新工具诞生,皆是对前人智慧的淬炼——萃取精华,摒弃沉疴。若技术苍穹仅存孤星,我们将失去选择最适合自身星座的权利,这何尝不是文明进程中的遗憾?
此刻,你还会认为重复造轮是种谬误吗?当每个轮毂都雕刻着创新的年轮,承载着不同的方向......