前端常见构建工具对比
前端模块化有个共同点:源代码无法直接运行,必须通过转换后才可以正常运行。而构建就是将源代码转换成发布到线上的可执行的 HTML、CSS 和 JavaScript 代码,构建工具就是指能自动对代码执行检验、转换、压缩等功能的工具,常见的功能有:
- 代码转换:例如将 TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等;
- 代码压缩:例如压缩 JavaScript、CSS、HTML 代码,压缩合并图片等;
- 代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载;
- 代码校验:在代码被提交到仓库前校验代码是否符合规范,以及单元测试是否通过;
- 自动刷新:监听本地源代码的变化,自动重新构建、刷新浏览器;
- 自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。
下面是常见的构建工具,多由 Node.js 开发。
一、Grunt
Grunt 是个 JavaScript 任务运行器,有大量封装常见任务的插件,可以灵活管理任务间的依赖和自动化执行依赖的任务。
Grunt 每个任务的具体依赖关系和执行代码写在配置文件 Gruntfile.js
中,在项目根目录下执行命令 grunt dev
就会启动 JavaScript 文件压缩和自动刷新功能。
Grunt 的优点
- 灵活,只负责执行定义的任务;
- 拥有大量封装好常见构建任务的可复用插件。
Grunt 的缺点
- 集成度不高,需要写很多配置后才能用,无法做到开箱即用。
二、Gulp
Gulp 是一个基于流的自动化构建工具。除了可以管理和执行任务,还支持监听读写文件。可以看作 Grunt 的加强版。相对于 Grunt,Gulp 增加了监听读写文件、流式处理的功能。
Gulp 设计得非常简单,只通过下面 5 个方法就可以胜任几乎所有构建场景:
- 通过 gulp.task 注册一个任务;
- 通过 gulp.run 执行任务;
- 通过 gulp.watch 监听文件变化;
- 通过 gulp.src 读取文件;
- 通过 gulp.dest 写文件。
Gulp 的最大特点是引入了流的概念,同时提供了一系列常用的插件去处理流,流可以在插件之间传递。
Gulp 的优点
- 好用又不失灵活,既可以单独完成构建也可以和其它工具搭配使用。
Gulp 的缺点是
- 和 Grunt 类似,集成度不高,要写很多配置后才可以用,无法做到开箱即用。
三、Rollup
Rollup 是一个专注于 ES6 模块化的模块打包工具,可将一小段代码编译成更大或更复杂的内容,例如库或应用程序。
Rollup 的优点
- 能针对 ES6 源码进行 Tree Shaking 以去除那些已被定义但未被引用的代码;
- 支持程序流分析,能更加正确的判断项目本身的代码是否有副作用。
Rollup 与 webpack 的区别
- Rollup 功能没 Webpack 完善(例如热重载和按需加载),但其配置和使用更加简单;
- Rollup 在打包 JavaScript 库的方面比 webpack 更加有优势,因为其打包出来的代码更小更快。
四、ESbuild
ESbuild 是一个类似 webpack 的构建工具,其构建速度是 webpack 的几十倍。vite 在底层使用了 esbuild 进行 JS、TS 文件的转化。
esbuild 的优点
- JS 是单线程串行,而 esbuild 是新开一个进程,然后多线程并行,充分发挥多核优势;
- esbuild 使用 Go 编写,Go 是纯机器码,比 JIT 快;
- esbuild 不使用 AST,优化了构建流程。
esbuild 的缺点
- 为了保证 esbuild 的编译效率,esbuild 没有提供 AST 的操作能力。所以通过 AST 处理代码的 babel-plugin 没有很好的方法过渡到 esbuild 中。
五、Webpack
webpack 是一个打包模块化 JavaScript 的工具,专注于构建模块化项目,在 webpack 里一切文件皆模块,它通过 Loader 转换文件,通过 Plugin 注入钩子,最后输出由多个模块组合成的文件。
webpack 的优点
- 专注于处理模块化项目,开箱即用;
- 通过 Plugin 扩展,完整好用又不失灵活;
- 强大的社区庞大活跃以及良好的开发体验。
webpack 的缺点
- 只能用于模块化开发的项目。
六、vite
vite 是一个最近兴起的构建工具,对标 webpack,基本上 webpack 有的功能它都有。其性能比 Vue-cli(基于 webpack)更强。
vite 的优点
- 快速的冷启动;
- 即时的模块热更新;
- 真正的按需编译;
- 内置 SSR 支持。
vite 的缺点
- 只能针对现代浏览器(ES6+)
- 与 CommonJS 模块不完全兼容;
- 对 React 的支持有限。