跳到主要内容

Webpack / Vite / Esbuild / Rollup 构建工具对比

前端项目离不开构建工具——它们负责把我们写的源代码(TypeScript、JSX、Vue SFC、Sass 等)转换成浏览器能理解的标准 HTML、CSS 和 JavaScript。目前最主流的四大构建工具分别是 WebpackViteEsbuildRollup。它们各有特色、定位不同,理解它们的异同,能帮助我们在不同场景下做出正确的技术选型。

一、四大工具简介

在对比之前,我们先对每个工具做一个简要认识,就像认识班上的四位同学一样——先了解各自的背景和特长。

1.1 Webpack —— 老牌全能选手

Webpack 诞生于 2012 年,是前端工程化浪潮中最早被广泛使用的打包工具。它的核心理念是万物皆模块——不仅 JS 可以被打包,CSS、图片、字体甚至 JSON 都可以通过 loader 机制变成模块参与打包。

核心特点

  • Loader 机制:通过不同的 loader 处理不同类型的文件(如 babel-loader 处理 JS、css-loader 处理 CSS)
  • Plugin 系统:通过插件扩展 Webpack 的几乎所有行为(如 HtmlWebpackPlugin 自动生成 HTML)
  • 代码分割:支持多种代码分割策略(入口分割、动态导入、SplitChunksPlugin)
  • 生态极其成熟:几乎所有你能想到的需求都有现成的 loader 或 plugin

1.2 Vite —— 新生代速度之王

Vite 由 Vue.js 作者尤雨溪于 2020 年创建,名字来自法语"快"的意思。它的核心创新是开发环境不打包——利用浏览器对原生 ES Modules 的支持,实现按需编译。

核心特点

  • 极速开发体验:冷启动毫秒级,HMR 不受项目规模影响
  • 双引擎架构:开发环境用 esbuild 预构建依赖,生产环境用 Rollup 打包
  • 开箱即用:内置 TypeScript、CSS Modules、PostCSS、静态资源处理等
  • 框架无关:虽然出自 Vue 团队,但同样完美支持 React、Svelte 等

1.3 Esbuild —— 极致性能的编译器

Esbuild 由 Figma 联合创始人 Evan Wallace 于 2020 年发布,使用 Go 语言编写。它不是一个完整的构建框架,更像是一个超高速编译引擎,主要负责代码的转译和打包。

核心特点

  • 极致速度:比传统 JS 构建工具快 10-100 倍
  • Go 语言编写:原生编译为机器码,无 JS 解释器开销
  • 内置能力:自带 JS/TS/JSX 转译、打包、压缩功能
  • API 简洁:提供 Transform API 和 Build API

1.4 Rollup —— 库打包专家

Rollup 诞生于 2015 年,由 Rich Harris(Svelte 的作者)创建,专注于 ES Modules 的打包。它是最早推广 Tree-shaking 概念的工具,特别适合用于打包 JavaScript 库。

核心特点

  • 原生 ESM 设计:从一开始就基于 ES Modules 标准
  • 出色的 Tree-shaking:精确消除未使用的代码,产出体积最小
  • 输出格式灵活:支持 ESM、CJS、UMD、IIFE 等多种格式
  • 插件生态丰富:Vite 的插件机制正是基于 Rollup 扩展

二、设计理念对比

四个工具的设计出发点不同,这决定了它们各自的优势领域。可以把它们想象成四种不同类型的交通工具——不是哪个更好,而是适合不同的场景。

维度WebpackViteEsbuildRollup
诞生年份2012202020202015
实现语言JavaScriptJavaScriptGoJavaScript
设计定位通用应用打包器开发框架 + 构建工具高速编译/打包引擎ES Modules 打包器
核心理念万物皆模块利用浏览器原生 ESM极致编译速度最优代码输出
开箱即用程度低(需大量配置)高(预设最佳实践)中(API 简洁但功能有限)中(需要插件补充能力)

三、构建模型与工作原理

这是四个工具最本质的区别——它们处理代码的方式截然不同。

3.1 Webpack:先打包、再启动

Webpack 采用的是经典的 Bundle-based 模式。无论开发还是生产,都需要先把所有模块分析、编译、打包成一个或多个 bundle 文件。

// webpack.config.js 典型配置
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
},
module: {
rules: [
// 每种文件类型都需要配置对应的 loader
{ test: /\.tsx?$/, use: 'ts-loader' },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
{ test: /\.(png|jpg|gif)$/, type: 'asset/resource' },
],
},
plugins: [new HtmlWebpackPlugin({ template: './index.html' })],
}

3.2 Vite:开发不打包、生产用 Rollup

Vite 的最大创新是开发阶段完全不打包。浏览器通过原生 ESM 按需请求模块,Vite 只在被请求时才编译返回。

// vite.config.ts 典型配置 —— 简洁得多
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
plugins: [vue()],
// 大部分功能开箱即用,无需像 Webpack 那样逐一配置
})

3.3 Esbuild:并行编译引擎

Esbuild 专注于做一件事——尽可能快地编译和打包代码。它将解析、编译、打包、压缩全部用 Go 实现,并充分利用多核并行处理。

// esbuild 的 Build API
const esbuild = require('esbuild')

esbuild.build({
entryPoints: ['src/index.ts'],
bundle: true,
outfile: 'dist/bundle.js',
minify: true,
sourcemap: true,
target: ['es2020'],
format: 'esm',
})
// esbuild 的 Transform API —— 单纯转译代码,不打包
const result = await esbuild.transform(tsCode, {
loader: 'ts',
target: 'es2020',
})
console.log(result.code) // 转译后的 JS 代码

3.4 Rollup:以 ESM 为中心的打包

Rollup 从一开始就围绕 ES Modules 设计,它对 import/export 有深入的静态分析能力,因此能做出最精确的 Tree-shaking。

// rollup.config.js 典型配置
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import terser from '@rollup/plugin-terser'

export default {
input: 'src/index.js',
output: [
{ file: 'dist/bundle.esm.js', format: 'es' }, // ESM 格式
{ file: 'dist/bundle.cjs.js', format: 'cjs' }, // CommonJS 格式
{ file: 'dist/bundle.umd.js', format: 'umd', name: 'MyLib' }, // UMD 格式
],
plugins: [resolve(), commonjs(), terser()],
}

四、性能对比

性能是开发者最关心的维度之一。我们从启动速度、构建速度、热更新三个角度进行对比。

4.1 开发启动速度

以一个包含 1000 个模块的中型项目为例:

指标Webpack 5ViteEsbuildRollup
冷启动时间10-30s0.3-1s0.1-0.5s通常不用于开发
启动方式先打包再启动预构建依赖后即启动极速打包-
与项目规模关系线性增长几乎无关线性但斜率极小-
为什么 Vite 启动快?

Webpack 的启动过程是"先打包全部代码 → 再启动服务",而 Vite 是"直接启动服务 → 浏览器请求时才编译"。就像去餐厅吃饭——Webpack 是等所有菜做好了一起上桌,Vite 是点哪道菜就先做哪道。

4.2 生产构建速度

以同一个 React 项目(10 倍规模的典型应用)为参考基准:

工具实现语言构建耗时相对速度
esbuildGo~0.37s🏆 1x(基准)
Parcel 2Rust + JS~17.8s~48x
Rollup + terserJavaScript~32.1s~87x
Webpack 5JavaScript~41.2s~111x
速度差异的根本原因

esbuild 的速度优势来源于四个方面:① Go 语言编译为原生机器码,无 JS 解释器开销;② 大量使用并行处理,充分利用多核 CPU;③ 从零自主实现所有功能,无第三方依赖开销;④ 高效的内存管理,减少 GC 压力。传统 JS 工具在单线程 Node.js 环境下运行,天然无法与之竞争。

4.3 热更新(HMR)速度

特性WebpackViteEsbuildRollup
HMR 支持✅ 内置✅ 内置❌ 不内置❌ 不内置
更新粒度重新打包受影响的 chunk只更新变更的模块--
与项目规模关系随项目变大而变慢始终恒定--
典型更新耗时100ms - 数秒< 50ms--

五、功能特性全面对比

5.1 核心功能矩阵

功能WebpackViteEsbuildRollup
JavaScript 打包
TypeScript 转译✅ 需 loader✅ 内置✅ 内置✅ 需插件
JSX/TSX 支持✅ 需 loader✅ 内置✅ 内置✅ 需插件
CSS 处理✅ 需 loader✅ 内置⚠️ 基础支持✅ 需插件
CSS Modules✅ 需配置✅ 内置✅ 需插件
CSS 预处理器✅ 需 loader✅ 安装即用✅ 需插件
静态资源处理✅ 内置✅ 内置⚠️ 基础✅ 需插件
代码分割✅ 强大灵活✅ 基于 Rollup✅ 基础支持✅ 灵活
Tree-shaking✅ 支持✅ 优秀(Rollup)✅ 基础✅ 🏆 最优
代码压缩✅ terser/esbuild✅ esbuild/terser✅ 内置✅ 需插件
Source Map
HMR✅ 🏆 最快
开发服务器✅ webpack-dev-server✅ 内置❌ 需自行搭建❌ 需插件
HTML 处理✅ 需插件✅ 内置✅ 需插件
环境变量✅ DefinePlugin✅ 内置✅ define 选项✅ 需插件
多入口/多页面

5.2 Tree-shaking 能力对比

Tree-shaking(树摇)是构建工具中一项关键的优化技术,用于移除代码中未被使用的部分,就像摇晃一棵树让枯叶掉落。

// math.js —— 导出两个函数
export function add(a, b) {
return a + b
}

export function multiply(a, b) {
return a * b
}

// main.js —— 只用了 add
import { add } from './math.js'
console.log(add(1, 2))
// multiply 函数是"死代码",应该被移除
工具Tree-shaking 能力说明
Rollup🏆 最优原生基于 ESM 静态分析,最精确的死代码检测
Vite优秀生产环境借助 Rollup,效果等同
Webpack良好支持 Tree-shaking,但对 CJS 模块效果有限
Esbuild基础支持基本的 Tree-shaking,但精确度不如 Rollup
Rollup 的 Tree-shaking 为什么最好?

Rollup 从设计之初就围绕 ES Modules 的静态结构(import/export 在编译时就能确定)来做分析。它能深入分析每个变量、函数的使用情况,精确到单个导出。而 Webpack 由于需要兼容 CommonJS 等动态模块系统,在 Tree-shaking 的精确度上会有所折扣。

5.3 代码分割策略

代码分割是将一个大的 bundle 拆成多个小 chunk,实现按需加载,减少首屏加载体积。

策略WebpackVite/RollupEsbuild
入口分割✅ 多 entry 配置✅ 多入口✅ 多入口
动态导入import()import()import()
共享 chunk 提取✅ SplitChunksPlugin(高度可配置)✅ manualChunks(灵活)⚠️ 基础支持
CSS 代码分割✅ MiniCssExtractPlugin✅ 内置支持❌ 不支持
自定义分割策略✅ 非常灵活✅ 灵活⚠️ 有限
// Webpack 的代码分割配置
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
common: {
minChunks: 2,
name: 'common',
chunks: 'all',
},
},
},
},
}

// Vite/Rollup 的代码分割配置
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
utils: ['lodash-es', 'dayjs'],
},
},
},
},
})

六、插件/扩展生态

构建工具的扩展能力决定了它能应对多复杂的场景。

6.1 扩展机制对比

维度WebpackViteEsbuildRollup
扩展机制Loader + PluginPlugin(兼容 Rollup)PluginPlugin
钩子数量非常多(40+)较多(Rollup 钩子 + Vite 专有钩子)较少(2 个核心钩子)适中(20+)
生态成熟度🏆 最成熟快速增长较少成熟
社区插件数量数千个数百个(+可用 Rollup 插件)较少数百个
上手难度较高中等较低中等

6.2 典型插件示例

Webpack 的 Loader + Plugin 模式

// Webpack 需要 Loader 来处理非 JS 文件
module.exports = {
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader', // 处理 Vue 单文件组件
},
{
test: /\.svg$/,
loader: 'svg-inline-loader', // 内联 SVG
},
],
},
plugins: [
new VueLoaderPlugin(), // Vue Loader 的配套插件
new MiniCssExtractPlugin(), // CSS 提取插件
new BundleAnalyzerPlugin(), // 打包分析插件
],
}

Vite Plugin 模式(兼容 Rollup):

// 一个 Vite 插件既能在开发服务器中工作,也能在生产构建中工作
import type { Plugin } from 'vite'

function myVitePlugin(): Plugin {
return {
name: 'my-plugin',
// Rollup 钩子 —— 开发和构建都会执行
transform(code, id) {
if (id.endsWith('.custom')) {
return { code: transformCustomFile(code) }
}
},
// Vite 专有钩子 —— 只在开发服务器中执行
configureServer(server) {
// 自定义开发服务器行为
},
}
}

Esbuild Plugin 模式(简洁但功能有限):

// esbuild 插件只有两个核心钩子
const myPlugin = {
name: 'my-plugin',
setup(build) {
// 拦截模块解析
build.onResolve({ filter: /\.custom$/ }, (args) => {
return { path: resolve(args.resolveDir, args.path) }
})
// 拦截模块加载
build.onLoad({ filter: /\.custom$/ }, (args) => {
const content = readFileSync(args.path, 'utf8')
return { contents: transform(content), loader: 'js' }
})
},
}

七、配置复杂度对比

配置的简易程度直接影响开发者的使用体验和上手速度。

7.1 相同需求下的配置对比

假设需要搭建一个同时支持 TypeScript + Vue 3 + CSS Modules + 路径别名 的项目:

Webpack 配置(约 40-60 行):

const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
entry: './src/main.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
clean: true,
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.vue'],
alias: { '@': path.resolve(__dirname, 'src') },
},
module: {
rules: [
{ test: /\.vue$/, loader: 'vue-loader' },
{ test: /\.ts$/, loader: 'ts-loader', options: { appendTsSuffixTo: [/\.vue$/] } },
{
test: /\.module\.css$/,
use: ['style-loader', { loader: 'css-loader', options: { modules: true } }],
},
{ test: /\.css$/, exclude: /\.module\.css$/, use: ['style-loader', 'css-loader'] },
],
},
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({ template: './index.html' }),
],
devServer: { hot: true, port: 3000 },
}

Vite 配置(约 10-15 行):

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'

export default defineConfig({
plugins: [vue()],
resolve: {
alias: { '@': path.resolve(__dirname, 'src') },
},
// TypeScript、CSS Modules、HMR、开发服务器 —— 全部开箱即用!
})

对比一目了然——Vite 将大量"合理默认值"内置为零配置功能,而 Webpack 需要开发者手动配置每个细节。

7.2 配置复杂度总结

维度WebpackViteEsbuildRollup
零配置可用性❌ 基本不可用✅ 大部分场景开箱即用✅ 简单场景可用⚠️ 需基础配置
典型配置行数50-200+ 行10-30 行10-20 行20-50 行
学习曲线陡峭平缓较平缓中等
需安装的依赖数多(各种 loader/plugin)少(大部分内置)极少(仅 esbuild)中等(需要插件)

八、适用场景与技术选型

8.1 场景推荐矩阵

8.2 详细选型指南

场景推荐工具理由
新建 Web 应用(React/Vue/Svelte)Vite开箱即用、极快的开发体验、社区活跃
大型老项目(已使用 Webpack)Webpack迁移成本高,可优先升级到 Webpack 5 优化性能
打包 JS/TS 库Rollup最优的 Tree-shaking、灵活的输出格式(ESM/CJS/UMD)
组件库打包RollupVite 库模式多格式输出、精确的 Tree-shaking
底层工具的编译引擎Esbuild极致的编译速度,适合作为其他工具的底层
需要极致控制的构建Webpack最灵活的配置、最丰富的插件生态
SSR 框架(Nuxt/Next.js)框架内置(通常是 Vite 或 Webpack)框架已做好配置,直接使用
Monorepo 项目ViteWebpack 5Vite 天然支持 Monorepo;Webpack 5 的 Module Federation 适合微前端

8.3 实际项目中的混合使用

在实际项目中,这些工具往往是协作关系而非单纯的竞争关系:

一些常见的混合使用模式:

  • Vite = esbuild(开发编译)+ Rollup(生产打包)
  • Webpack + esbuild-loader:用 esbuild 替代 babel-loader 来加速 Webpack 的编译
  • 组件库项目:用 Vite 做开发调试,用 Rollup 做最终发布打包

九、未来趋势

前端构建工具正在经历一场语言层面的变革——从 JavaScript 编写的工具转向 Rust/Go 等系统语言编写的工具,以获得数量级的性能提升。

新兴工具实现语言定位与现有工具的关系
TurbopackRustWebpack 的继任者由 Webpack 作者打造,被 Next.js 采用
RolldownRustRollup 的替代品Vite 团队开发,未来将统一 Vite 的开发和生产构建
FarmRust新一代全功能构建工具独立项目,兼容 Vite 插件生态
SWCRust编译工具替代 Babel,被 Next.js、Deno 采用
OxcRust全栈 JS 工具链目标替代 ESLint、Prettier、Babel 等
Rolldown —— Vite 的未来统一方案

Vite 当前使用两套引擎(esbuild + Rollup)导致开发和生产环境存在行为差异。Rolldown 的目标是用 Rust 实现一个 Rollup 兼容的高性能打包器,同时承担预构建和生产打包,彻底解决这个问题。这意味着未来的 Vite 将拥有更一致的行为和更快的构建速度。

十、总结速查表

维度WebpackViteEsbuildRollup
定位通用应用打包器现代开发框架高速编译引擎ESM 打包器
实现语言JavaScriptJS(底层用 Go/Rust)GoJavaScript
开发启动慢(先打包)🏆 快(按需编译)极快不适用
生产构建中等较快🏆 最快中等
HMR较慢🏆 最快不支持不支持
Tree-shaking良好优秀基础🏆 最优
配置复杂度🏆 低中等
插件生态🏆 最丰富快速增长较少丰富
适用场景大型/复杂应用新建 Web 应用底层编译引擎库/组件库打包
学习曲线陡峭🏆 平缓平缓中等
社区活跃度成熟稳定🏆 最活跃活跃稳定

一句话总结每个工具的核心价值:

  • Webpack:最全面的打包能力,复杂场景的终极武器
  • Vite:最佳开发体验,新项目的首选方案
  • Esbuild:最极致的编译速度,工具链的底层引擎
  • Rollup:最优的代码输出,库打包的最佳选择

十一、面试高频问答

Q1:Webpack、Vite、Esbuild、Rollup 四者的核心区别是什么?

:四个工具的定位不同。Webpack 是通用的应用打包器,通过 Loader + Plugin 机制实现"万物皆模块",生态最成熟。Vite 是现代开发框架,开发环境利用浏览器原生 ESM 按需编译(不打包),生产环境用 Rollup 打包,核心优势是极快的开发体验。Esbuild 是用 Go 语言编写的超高速编译引擎,速度比传统 JS 工具快 10-100 倍,但功能相对有限,常作为其他工具的底层引擎(如 Vite 用它做预构建)。Rollup 专注于 ES Modules 的打包,Tree-shaking 能力最强,输出格式灵活,特别适合打包 JS 库。


Q2:为什么 Vite 比 Webpack 开发启动快那么多?

:根本原因在于两者的开发模型不同。Webpack 采用"先打包、再启动"的模式——启动时需要分析完整的模块依赖图、编译所有模块、生成 bundle 后才能启动开发服务器,项目越大启动越慢。Vite 采用"先启动、按需编译"的模式——直接启动开发服务器,利用浏览器原生 ESM 能力,只在浏览器请求某个模块时才即时编译返回。同时 Vite 用 Go 语言编写的 esbuild 处理依赖预构建,速度远超 JavaScript 工具。因此 Vite 的启动速度几乎不受项目规模影响。


Q3:Esbuild 为什么那么快?

:Esbuild 的极致速度来源于四个方面:① Go 语言编写,编译为原生机器码执行,没有 JavaScript 解释器的运行时开销;② 大量并行处理,Go 的 goroutine 能够充分利用多核 CPU 并行地做解析、编译和打包;③ 从零自主实现,所有的词法分析、AST 解析、代码转换、代码生成都自行实现,没有第三方依赖的额外开销;④ 高效的内存管理,数据结构和算法经过精心优化,减少内存分配和垃圾回收的压力。


Q4:为什么打包 JS 库推荐用 Rollup 而不是 Webpack?

:Rollup 在打包 JS 库方面有三个核心优势。一是 Tree-shaking 最精确,Rollup 原生基于 ESM 静态分析,能精确到每个导出的使用情况,生成的产物体积最小,库的使用者能获得更好的 Tree-shaking 效果。二是输出格式灵活,可以同时输出 ESM、CJS、UMD、IIFE 等多种格式,适配不同的消费场景(浏览器直引、Node.js require、打包工具 import 等)。三是输出代码更简洁,Rollup 生成的代码几乎没有运行时辅助代码,而 Webpack 会注入自己的模块加载运行时(__webpack_require__ 等),对于库来说这些是不必要的开销。


Q5:Vite 为什么生产环境不直接用浏览器原生 ESM?

:虽然原生 ESM 在开发环境效果很好,但在生产环境中直接使用存在几个问题:① 嵌套导入导致请求瀑布——深层的模块 import 链会导致大量串行的 HTTP 请求,即使 HTTP/2 也无法完全解决;② 无法 Tree-shaking——浏览器只负责加载模块,不会做死代码消除;③ 无法优化代码分割——缺少智能的 chunk 拆分策略来平衡首屏体积和按需加载;④ 缺少资源优化——无法进行代码压缩、CSS 提取合并、图片压缩、添加文件哈希等优化。因此生产环境仍然需要打包工具来产出优化后的静态资源。


Q6:Vite 的双引擎架构(esbuild + Rollup)有什么问题?

:Vite 在开发环境使用 esbuild 预构建依赖,在生产环境使用 Rollup 打包,这种双引擎架构存在行为不一致的风险——同一段代码在开发和生产环境可能被不同的引擎以不同的方式处理,偶尔会出现"开发没问题、上线有 Bug"的情况。Vite 团队为此开发了 Rolldown(一个用 Rust 编写的 Rollup 替代品),目标是用一个统一的引擎同时处理开发预构建和生产打包,从根本上消除双引擎带来的差异。


Q7:什么场景下仍然应该选择 Webpack?

:以下场景 Webpack 仍然是合理的选择:① 大型老项目——已经深度使用 Webpack 的项目,迁移成本高、风险大,可以先升级到 Webpack 5 获得性能提升;② 需要 Module Federation——Webpack 5 的模块联邦特性在微前端架构中非常有用,目前其他工具还无法完全替代;③ 需要极致的定制化——Webpack 拥有最丰富的 Loader 和 Plugin 生态,几乎任何需求都能找到解决方案;④ 特殊的兼容性需求——需要支持非常老的浏览器或复杂的 polyfill 策略。不过对于新项目,建议首选 Vite。


Q8:前端构建工具未来的发展趋势是什么?

:前端构建工具正在经历三大趋势。第一是系统语言化——从 JavaScript 编写转向 Rust/Go 编写,如 Turbopack(Rust,Webpack 继任者)、Rolldown(Rust,Rollup 替代)、SWC(Rust,Babel 替代)、Oxc(Rust,全栈工具链),追求数量级的性能提升。第二是工具链统一化——从各工具各自为战走向整合,如 Vite 的 Rolldown 将统一开发和生产构建、Oxc 目标整合 lint/format/compile 等能力到一个工具链中。第三是零配置化——Next.js、Nuxt 等框架将构建配置封装在框架内部,开发者越来越少需要直接操作构建工具的配置。