主要优化方向:
- 提高构建效率:指从源代码到最终产物的转换速度,包括编译、打包、优化等环节的耗时。
- 添加构建缓存:通过缓存编译结果,避免重复编译未变更的文件,大幅提升二次构建速度。
- 缩小文件搜索范围 :通过配置
include/exclude限制 loader 处理的文件范围,减少不必要的文件扫描。
1. 编译速度优化
SWC(Speedy Web Compiler) :基于 Rust 编写的编译器,编译速度比 Babel 快 10-70 倍。SWC 常用于替代 Babel 以提升编译性能,在 Vite 的 React 项目中可通过 @vitejs/plugin-react-swc 启用。
- 编译速度快:基于 Rust 编写,性能远超 JavaScript 实现的 Babel。
- 功能完整:支持 ES6+、TypeScript、JSX 等语法转换。
- 兼容性好:大多数语法转换场景下可以替代 Babel,如果依赖 Babel 插件生态实现复杂转换,则还是需要 Babel 支持。
在基于 Vue-Cli5 的项目测试中,使用 Babel 的构建时间约 40s,使用 SWC 的构建时间约为 22s,提升了约 45%。
另一种是采用基于 Go 编写的 ESBuild 优化编译速度
Vue-cli 配置:
javascript
// vue.config.js
// 安装:npm install @swc/core swc-loader -D
module.exports = {
chainWebpack: (config) => {
// 移除旧 babel-loader 编译
config.module.rules.delete("js");
// 用 SWC 处理 JS/JSX 文件
config.module
.rule("js")
.test(/\.(js|jsx)$/) // 匹配 .js 和 .jsx 文件
.exclude.add(/node_modules/) // 排除 node_modules
.end()
.use("swc-loader")
.loader("swc-loader")
.options({
jsc: {
parser: {
syntax: "ecmascript", // 解析 ECMAScript 语法
jsx: true, // 支持 JSX(不影响 Vue)
dynamicImport: true, // 支持动态导入
},
target: "es2015", // 转译为 ES6 语法
},
sourceMap: process.env.NODE_ENV === "development", // 开发环境生成 SourceMap
});
// 如果项目使用 TypeScript,再添加 TS 处理(没有则删除这部分)
if (config.module.rules.has("ts")) {
config.module.rules.delete("ts");
config.module
.rule("ts")
.test(/\.(ts|tsx)$/) // 匹配 .ts 和 .tsx 文件
.exclude.add(/node_modules/)
.end()
.use("swc-loader")
.loader("swc-loader")
.options({
jsc: {
parser: {
syntax: "typescript", // 解析 TypeScript 语法
tsx: true, // 支持 TSX
},
target: "es2015",
},
sourceMap: process.env.NODE_ENV === "development",
});
}
},
};
2. 构建结果缓存
通过缓存编译结果,避免重复编译未变更的文件,可以大幅提升二次构建的速度。
工作原理:
- 首次构建时,编译所有文件,将结果缓存到磁盘。
- 二次构建时,检查文件是否变更,未变更的文件直接使用缓存结果。
- 当文件内容或配置变更时,会自动使对应缓存失效,重新构建。
Vue-cli 配置(Webpack 4) :手动使用 cache-loader 实现缓存,需要手动配置。
cache-loader主要用于 Webpack 4,在 Webpack 5 中已不再推荐使用。
javascript
// Webpack 4 - cache-loader 配置
// vue.config.js
// 安装:npm install cache-loader -D
module.exports = {
chainWebpack: (config) => {
// 为 babel-loader 添加缓存
// 注意:cache-loader 必须放在其他 loader 之前
config.module
.rule("js")
.test(/\.js$/) // 匹配 .js 文件
.exclude.add(/node_modules/) // 排除 node_modules
.end()
.use("cache-loader") // 先使用 cache-loader
.loader("cache-loader")
.options({
cacheDirectory: ".cache/babel-loader", // 缓存目录
})
.end()
.use("babel-loader") // 再使用 babel-loader
.loader("babel-loader");
// 为 CSS 处理添加缓存
config.module
.rule("css")
.test(/\.css$/) // 匹配 .css 文件
.use("cache-loader")
.loader("cache-loader")
.options({
cacheDirectory: ".cache/css-loader", // 缓存目录
})
.end()
.use("css-loader")
.loader("css-loader");
},
};
Vue-cli 配置(Webpack 5):内置持久化缓存机制,默认启用,无需额外配置。
javascript
// Webpack 5 - 内置缓存配置
// vue.config.js
const path = require("path");
module.exports = {
configureWebpack: {
cache: {
type: "filesystem", // 使用文件系统缓存(默认是 memory 内存缓存,重启后失效)
buildDependencies: {
config: [__filename], // 当配置文件变更时,使缓存失效
},
cacheDirectory: path.resolve(__dirname, ".cache/webpack"), // 缓存目录
compression: "gzip", // 压缩缓存文件,支持 gzip 和 brotli,开发环境默认关闭
maxAge: 1000 * 60 * 60 * 24 * 7, // 缓存有效期 7 天(毫秒,默认 1 个月)
},
},
};
Vite :默认启用文件系统缓存,缓存位置在 node_modules/.vite 目录中。如果代码修改后发现未更新,可以删除该目录来清除缓存。
javascript
// vite.config.js(Vite 内置缓存)
import { defineConfig } from "vite";
export default defineConfig({
// Vite 默认启用文件系统缓存,无需额外配置
// 缓存位置:node_modules/.vite
// 开发环境:缓存预构建的依赖
// 生产环境:缓存 Rollup 构建结果
build: {
// 生产构建缓存配置
rollupOptions: {
// Rollup 配置
},
},
});
3. 缩小文件搜索范围
通过 include/exclude 配置 loader 指向的范围空间,减少不必要的文件扫描,提升构建速度。
优化原理:
- include:指定 loader 只处理特定目录的文件,避免扫描无关目录。
- exclude :排除不需要处理的目录(如
node_modules),减少文件扫描量。 - resolve 配置:配置模块解析路径和别名,减少路径解析时间。
Vue-cli 配置:
javascript
// vue.config.js
const path = require("path");
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = {
chainWebpack: (config) => {
// JS 文件处理
config.module
.rule("js")
.test(/\.js$/)
.include.add(resolve("src")) // 只在 src 文件夹下查找
.end()
.exclude.add(/node_modules/) // 排除 node_modules
.end()
.use("babel-loader")
.loader("babel-loader");
// TypeScript 文件处理
config.module
.rule("ts")
.test(/\.ts$/)
.include.add(resolve("src"))
.end()
.exclude.add(/node_modules/)
.end()
.use("ts-loader")
.loader("ts-loader");
},
};
Vite 配置:
javascript
// vite.config.js
import { defineConfig } from "vite";
import { resolve } from "path";
export default defineConfig({
resolve: {
alias: {
"@": resolve(__dirname, "src"), // 配置别名,减少路径解析时间
},
// 指定文件扩展名解析顺序,按顺序尝试,找到即停止
extensions: [".js", ".vue", ".json", ".ts"],
},
// Vite 会自动排除 node_modules,无需手动配置
});
4. 环境配置优化
使用 Vite 代替 Webpack
Vite:基于 ESM 的构建工具,编译功能依赖于 Rollup 和 ESBuild 完成,开发环境使用原生 ESM,生产环境使用 Rollup 打包,构建速度更快。
优势:
- 依赖预构建:基于 ESBuild 预构建后无需重新打包,启动速度极快。
- 动态导入机制 :
- 传统打包方式是把所有文件编译后构建为 bundle,再启动 devServer 加载,这种模式导致冷启动和大项目下的构建成本较高。
- Vite 依赖了 ES6 的 ESM 模块机制,Vite 在开发阶段基于浏览器原生 ESM 进行模块加载,按模块请求进行即时转译与返回,从而显著降低冷启动成本。
- 缓存机制优化 :对于开发环境下的依赖模块采用
Cache-Control: max-age=31536000,immutable进行强缓存,源码则根据304 Not Modified进行协商缓存。
关闭 source-map
source-map:用于开发环境调试,但会显著增加构建时间。生产环境建议关闭。
建议:
- 开发环境 :使用快速 source-map(如
eval-cheap-module-source-map)。 - 生产环境:关闭 source-map,提升构建速度,同时避免源码结构暴露。
Vue-cli 配置:
javascript
// vue.config.js(Webpack)
module.exports = {
productionSourceMap: false, // 关闭生产环境 source map
configureWebpack: {
devtool:
process.env.NODE_ENV === "development"
? "eval-cheap-module-source-map"
: false,
},
};
Vite 配置:
javascript
// vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
build: {
sourcemap: false, // 生产环境关闭 source map
},
// 开发环境默认启用 source map,无需配置
});
5. 构建结果分析
这块应该补充在构建体积优化,但感觉本质也是体积压缩也是效率优化的一类
通过 webpack-bundle-analyzer(Vue-Cli)/ rollup-plugin-visualizer(Vite、Rollup)输出生产结果统计,分析打包体积,找出优化点:
- 被重复打包的组件和依赖/chunk 体积过大:通过异步组件/路由、splitChunk 抽离、webpackChunkName 进行优化。
- 占用较大体积的三方插件:查看是否有 ESM 版本支持 Tree-Shaking,查找按需引入方案(搜索 babel import 或 auto import 关键词)。
- 无需打包的模块:发现不用打包的依赖,分析其引入位置进行优化。

Vue-cli 配置:
javascript
// vue.config.js
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
module.exports = {
configureWebpack: {
plugins: [
// 配置环境变量,只在必要时开启
process.env.ANALYZE &&
new BundleAnalyzerPlugin({
analyzerMode: "static", // 分析模式:server(启动分析服务,默认)、static(生成 HTML 报告)、json(生成 JSON 报告)
openAnalyzer: false, // 不自动打开浏览器
reportFilename: "bundle-report.html", // 报告文件名
generateStatsFile: true, // 生成 stats.json
statsFilename: "bundle-stats.json",
}),
].filter(Boolean),
},
};
Vite 配置:
javascript
// vite.config.js(使用 rollup-plugin-visualizer)
import { defineConfig } from "vite";
import { visualizer } from "rollup-plugin-visualizer";
export default defineConfig({
plugins: [
visualizer({
open: false, // 构建后自动打开报告
filename: "dist/stats.html", // 报告输出路径
gzipSize: true, // 显示 gzip 压缩后的大小
brotliSize: true, // 显示 brotli 压缩后的大小
template: "treemap", // 可选:sunburst、treemap、network
}),
],
});
使用方式:
json
// package.json
{
"scripts": {
"analyze": "cross-env ANALYZE=true npm run build", // 分析打包体积
"build": "vue-cli-service build" // 正常构建
}
}
总结
- 核心优化策略
- 编译速度优化:使用 SWC 代替 Babel。
- 构建结果缓存 :Webpack 5 内置缓存或使用
cache-loader。 - 缩小搜索范围 :通过
include/exclude和resolve配置。 - 环境配置优化:使用 Vite 代替 Vue-Cli(Webpack)。
- 注意事项 :
- SWC 需要同时安装
@swc/core和swc-loader。 - Webpack 5 缓存默认启用,无需额外配置。
- 生产环境务必关闭 source-map,提升构建速度和安全性。
- 构建分析工具仅在需要时启用,避免影响正常构建速度。
- SWC 需要同时安装