前端构建工具的发展和现状:Webpack、Vite和其他

两条关键的线索

谈到前端构建工具,我们能想到常用的webpack、vite。不妨多想一步,它们是如何发展和壮大的呢?未来又是怎样的走向?

对于构建工具的发展,我总结了两个关键的线索,模块化和构建性能。

线索一:模块化

JavaScript模块化的发展,是构建工具变迁的重要因素。

有了CommonJS,才有Browserify/Webpack这种将众多 CommonJS 模块组合到一个 bundle 中的构建工具。

有了ESM标准,才有Rollup的出现,Webpack也跟着支持了ESM模块。随着浏览器大量支持ESM,才有了Vite。

线索二:构建性能

Web项目越来越大,对于构建性能的要求也越来越高。只使用JavaScript编写的构建工具不能满足性能要求,所以出现了SWC、esbuild等其他语言编写的构建工具。

模块化的发展

为了方便我们更好的梳理构建工具的发展脉络,先简单回顾一下模块化的发展路径。

IIFE

IIFE(Immediately Invoked Function Expression,即"立即调用函数表达式")是一种 JavaScript 编程模式,用于创建一个立即执行的函数。这种模式常用于隔离作用域,避免变量污染全局命名空间。

最早知道这个语法是从jquery中看到的。基本语法如下:

javascript 复制代码
(function() {
    // jquery的代码在这里执行
})();

// 在页面中通过script代码块引用
<script src="jquery.js"></script>

局限:当页面中引入很多的js脚本,并且这些脚本有依赖关系要使用彼此的功能时,这种模块方式很难支持。

AMD

AMD(Asynchronous Module Definition,即"异步模块定义")是一种用于定义和加载模块的 JavaScript 模块化规范。它主要用于浏览器环境,旨在解决模块化和异步加载的问题。

RequireJS 是 AMD 规范的一个流行实现。它提供了一个简单的 API 来加载和管理模块,并支持配置和优化。

javascript 复制代码
// 定义一个模块
define('math', [], function() {
    return {
        add: function(x, y) {
            return x + y;
        }
    };
});

// 使用模块
require(['math'], function(math) {
    console.log(math.add(2, 3)); // 输出: 5
});

局限:当我们要管理大量的依赖时,直接开发符合AMD规范的代码也是相当麻烦的。

CommonJS

CommonJS 是一种用于 JavaScript 的模块化规范,最初是为了在服务器端环境(如 Node.js)中使用而设计的。它提供了一种简单而有效的方式来组织和管理代码,使得开发者可以将代码分割成独立的模块,提升代码的可维护性和重用性。

javascript 复制代码
// math.js
function add(x, y) {
    return x + y;
}

function subtract(x, y) {
    return x - y;
}

module.exports = {
    add,
    subtract
};
javascript 复制代码
// main.js
const math = require('./math');

console.log(math.add(5, 3));       // 输出: 8
console.log(math.subtract(5, 3));  // 输出: 2

ESM

ESM(ECMAScript Modules)是 JavaScript 的官方模块系统,作为 ECMAScript 2015(ES6)的一部分引入。ESM 提供了一种标准化的方式来定义和使用模块,使得 JavaScript 在浏览器和服务器端环境中都能更好地进行模块化开发。

javascript 复制代码
// math.js
export function add(x, y) {
    return x + y;
}

export function subtract(x, y) {
    return x - y;
}

// 或者使用默认导出
export default function multiply(x, y) {
    return x * y;
}
javascript 复制代码
// main.js
import { add, subtract } from './math.js';
import multiply from './math.js';

console.log(add(5, 3));       // 输出: 8
console.log(subtract(5, 3));  // 输出: 2
console.log(multiply(5, 3));  // 输出: 15

它的静态结构和异步加载特性使得代码更容易管理和优化。随着浏览器和 Node.js 对 ESM 的广泛支持,ESM 已成为前端和后端开发的主流选择。

Webpack和它的对手们

一个故事总有一个主角,即使是《权力的游戏》这样的群像剧也有个大男主,我们这个故事的大男主就是Webpack,我准备围绕它来叙述构建工具们的诞生与发展。

Browserify

第一个出场的角色是Browserify。于2011 年发布。注意这个时间点,CommonJS于2009 年随着Node.js第一个版本发布。两年后出现了Browserify。

Browserify 旨在将 Node.js 风格的 CommonJS 模块打包成可以在浏览器中运行的代码。在浏览器环境下,JavaScript 原本并不支持 CommonJS 模块系统,因此需要像 Browserify 这样的工具来桥接这两个环境的差异。

局限:Browserify虽然完成的打包的任务,但是没有很好的支持代码分割和异步加载。

Webpack登场

于是乎,我们的主角登场了(2012 年),它不但可以将众多 CommonJS 模块组合到一个 bundle 中,还对代码分割、动态加载和热模块替换等进行了很好的支持(这些功能在现代 Web 开发中变得越来越重要)。大大的提升了构建体验。

Webpack没有止步不前。 2017 年 1 月,Webpack 2 引入了对 ES6 模块( ESM在2015年提出,也就是ECMAScript 2015(也称为 ES6)中引入)的原生支持,并改进了代码拆分和 Tree Shaking 功能。2017 年 6 月,这个版本引入了 Scope Hoisting,以提高打包后的代码执行性能。

Parcel:第一个反派

Webpack此时有个比较大的问题就是配置繁琐,此时它迎来了人生中的第一个大反派,Parcel。

2017 年 11 月,Parcel发布了第一个版本,主打的就是零配置。吸引了许多开发者的关注。

Webpack的反击

2018 年 2 月,Webpack 4 发布。这个版本中Webpack给出了自己的回击。也提升了配置体验。

Webpack 4 带来了显著的性能改进,并引入了零配置模式(mode),开发者可以选择开发模式或生产模式。此外,还增加了对 WebAssembly 的支持。

Rollup:又一个对手

Rollup的打法是专注于 ES 模块打包。显然这种打法为自己争夺了一块领土,在前端构建工具的世界中拥有了自己的一块领土。

Rollup 的最初版本是在 2015 年发布的。在后续不断发展壮大,后续被Vite招入麾下。

Rollup诞生

回到模块化发展的线索:IIFE -> AMD -> CommonJS -> ESM。

随着ESM模块化的发布,如同当初Browserify专注于将 CommonJS 模块打包以供浏览器使用。自然要出现专注于ES Module(ESM)的打包工具,即Rollup。Rollup 利用 ESM 的静态分析能力来进行高级优化,如 tree-shaking,这在构建库和应用时非常有用。

虽然Webpack有这很大的市场,但是Rollup同样也有一席之地。

Vite:新一季的主角

时间来到2020年,Webpack还在精进自我,发布了第5个版本,这个版本引入了持久化缓存、模块联邦(Module Federation)、改进的 Tree Shaking 和更好的 WebAssembly 支持。此时的Webpack已是构建工具领域真正的王者。

但这个国度从来不缺乏挑战者,随着浏览器对ESM的支持越来越好,新的角色闪亮登场。

Snowpack

真正的主角出现之前,往往会出现一个疑似主角的人,它就是Snowpack。

2020年初发布了Snowpack。旨在通过利用原生 ES 模块(ESM)来加速开发过程。Snowpack 的设计初衷是减少开发时的构建时间,通过在浏览器中直接使用 ES 模块,从而避免了传统打包工具的复杂性和性能瓶颈。

Vite

Snowpack没有笑到最后,这个世界有了一个更好的工具Vite。同样是借助于浏览器对于ESM的广泛支持,Vite专注于提升开发体验。并在之后逐渐壮大,在后续的版本中逐渐完善自己。

  • Vite 1.0- 发布于 2020 年 6 月。Vite 1.0 引入了即时的模块热替换和快速的开发服务器,专注于提升开发体验。
  • Vite 2.0- 发布于 2021 年 2 月。Vite 2.0 带来了对多种框架(如 Vue、React、Preact、Svelte 等)的更好支持,以及对 Rollup 插件生态系统的兼容性。
  • Vite 3.0- 发布于 2022 年 7 月。Vite 3.0 提升了性能,改进了插件系统,并更新了许多默认配置以支持更广泛的使用场景。
  • Vite 4.0- 发布于 2023 年 6 月。Vite 4.0 继续优化性能,增加了对新的 JavaScript 和 CSS 特性的支持,并改善了开发和构建体验。

Vite和esbuild、rollup之间的关系

俗话说团结就是力量,Vite选择了两个弟兄帮助自己成为好用的工具。

  • 开发阶段:在开发模式下,Vite 使用 ESBuild 来处理 JavaScript 和 TypeScript 的转换。这是因为 ESBuild 以极高的速度编译代码,能够显著提升开发体验。ESBuild 的快速处理能力使得 Vite 可以实现即时模块热更新(HMR),让开发者在修改代码时几乎立即看到变化。
  • 生产构建阶段:在生产环境下,Vite 使用 Rollup 作为打包工具。Rollup 是一个成熟的打包工具,擅长处理 ES 模块,拥有丰富的插件生态和强大的优化能力。

Vite结合了 ESBuild 和 Rollup 的优势:在开发阶段利用 ESBuild 的速度,在生产阶段利用 Rollup 的优化能力。

小结

紧随着线索一,随着模块化的发展,产出了诸多构建工具,其中的佼佼者Webpack和Vite脱颖而出。但是构建工具的王国还存在一个重大的挑战,也就是线索二说的事,前端项目越来越大越来越复杂,性能问题一直困扰着前端开发者们,我们急需性能强大的构建工具。

新的挑战:构建性能

在这个篇章里,首先向我们走来的是SWC和esbuild。

SWC:Babel的替代者

SWC(Speedy Web Compiler)是一个用 Rust 编写的 JavaScript/TypeScript 编译器,旨在提供快速的编译速度和高效的代码转换。它的主要目标是替代 Babel 等传统 JavaScript 编译器,提供更快的性能,特别是在大型项目中。

2017 年kdy1 开始写 SWC。

2021 年,kdy1 加入了 Vercel 团队,SWC 也成了 Next.js 的默认转译器。

如果我们的项目使用的Webpack,可以考虑使用swc-loader来提升构建速度。

总结:SWC归根结底只是一个编译器,并不能整体解决构建性能的问题,我们期待一些大角色。

esbuild:为解决性能瓶颈而生

2020 年初,Evan Wallace开始开发这个项目。esbuild 是用 Go 编写的,这使得它在编译速度上非常快。

目前被vite纳入麾下,作为开发环境的构建工具。

缺陷:esbuild 非常快,但是对构建资源优化的控制非常有限,并且插件API不够灵活;

从目前的苗头看,esbuild也不是真正的版本之子,还得看看其他工具可以成为本季的新主角。

Turbopack:Webpack作者的新儿子

Turbopack是由Webpack的创建者Tobias Koppers和Next.js团队使用Rust语言开发的,由 Vercel 于 2022 年 10 月首次发布。它的主要目标是取代Webpack,成为下一代前端构建工具。Turbopack的设计理念是提供极快的构建速度和开发体验。

这里Rust成为了引领前端基建的宠儿,Turbopack就是用Rust编写。

可以想到Webpack作者已然明白在旧的Webpack上已经没有性能优化的余地,需要使用Rust开新坑,用全新的工具解决性能问题,至于在未来能获得多少开发者的青睐,让我们拭目以待吧。

Rolldown:Vite的痛点与解决之道

Vite 的痛点在发布时就存在,即它的两个兄弟。

  • esbuild 非常快,但是对构建资源优化的控制非常有限,并且插件API不够灵活;
  • Rollup 成熟且灵活,但与本地打包工具相比仍然较慢,并且ESM/CJS互操作的处理还有待改进。

所以,如果能有一个具有本地速度和 Rollup 的灵活性的打包工具,那太好了。它就是Rolldown。

Vite 团队正在研发 Rolldown,它是使用 Rust 开发的 Rollup 替代品。最终,Rolldown 的目标并不是取代现有的工具,而是更好地满足在 Vite 中所面临的独特需求,并最终使所有使用 Vite 的用户受益。

Rspack:字节人想出的新办法

这里重点引入了Rspack官网上与turbopack的不同的说法。在我看来它两个是同一层次的竞品。

与 turbopack 不同的是,Rspack 选择了对 webpack 生态兼容的路线,一方面,这些兼容可能会带来一定的性能开销,但在实际的业务落地中,我们发现对于大部分的应用来说,这些性能开销是可以接受的,另一方面,这些兼容也使得 Rspack 可以更好地与上层的框架和生态进行集成,能够实现业务的渐进式迁移。

React和Vue的脚手架们

这里还要花一个小篇幅来说一下脚手架们,我们知道编写一个项目,不止有构建工作,还有些必要的初始化工作,这就需要脚手架了。脚手架也理所当然的要集成构建工具。

Create React App

Create React App(CRA)是一个由 Facebook 开发的命令行工具,用于快速创建和设置 React 应用程序的项目结构。内置了Webpack。

Vue CLI

用于构建vue项目。也是内置了Webpack的脚手架,现在已经不推荐使用,因为vue使用了Vite。

create-vue

用于构建vue项目。帮助构建基于Vite的Vue项目脚手架。

总结

故事现在看来还远远没有完结,2025年,让我们持续关注它们的新进展吧。希望在未来有更好用、性能更优异的构建工具为我们开发者使用。

相关推荐
觉醒法师几秒前
HarmonyOS开发 - 电商App实例二( 网络请求http)
前端·http·华为·typescript·harmonyos·ark-ts
沈剑心几秒前
Kotlin的协程,真能提升编程效率么?
android·前端·kotlin
堕落年代11 分钟前
Vue主流的状态保存框架对比
前端·javascript·vue.js
OpenTiny社区22 分钟前
TinyVue的DatePicker 组件支持日期面板单独使用啦!
前端·vue.js
冴羽22 分钟前
Svelte 最新中文文档教程(22)—— Svelte 5 迁移指南
前端·javascript·svelte
树上有只程序猿26 分钟前
Vue3组件通信:多个实战场景,轻松玩转复杂数据流!
前端·vue.js
剪刀石头布啊34 分钟前
css属性值计算过程
前端·css
bin915339 分钟前
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14基础固定表头示例
前端·javascript·vue.js·ecmascript·deepseek
小华同学ai41 分钟前
吊打中文合成!这款开源语音神器效果炸裂,逼真到离谱!
前端·后端·github
颜酱1 小时前
后台系统从零搭建(三)—— 具体页面之部门管理(抽离通用的增删改查逻辑)
前端·javascript·react.js