Tree Shaking 在 Vite 项目中是默认启用的,但为了确保最佳效果,你可以采取以下措施来优化未使用代码的移除:
1. 确保使用 ES 模块语法
Vite 默认支持 ES 模块的 Tree Shaking,所以你的代码应该:
// 正确 - 使用 ES 模块导入导出
import { functionA } from './moduleA'
export const functionB = () => {}
// 避免 - CommonJS 语法无法被 Tree Shaking
const _ = require('lodash')
module.exports = {}
2. 配置 Vite 优化选项
在 vite.config.js
中:
import { defineConfig } from 'vite'
export default defineConfig({
build: {
// 生产构建的特定配置
minify: 'terser', // 或 'esbuild'
terserOptions: {
compress: {
// 删除未使用的代码
unused: true,
// 删除调试代码
drop_console: true,
drop_debugger: true,
},
},
// 启用更激进的 Tree Shaking
rollupOptions: {
output: {
manualChunks: undefined, // 让 Rollup 自动处理代码分割
},
},
},
})
3. 处理第三方库
对于第三方库:
-
优先选择 ES 模块版本:
// 使用 lodash-es 而不是 lodash import { debounce } from 'lodash-es'
-
在 package.json 中标记副作用:
{ "sideEffects": false, // 或者明确列出有副作用的文件 "sideEffects": [ "*.css", "*.scss", "**/*.vue" ] }
4. 按需导入组件
对于组件库(如 Element Plus、Ant Design Vue):
// 正确 - 按需导入
import { Button } from 'element-plus'
// 避免 - 全量导入
import ElementPlus from 'element-plus'
5. 验证 Tree Shaking 效果
-
构建分析:
import { defineConfig } from 'vite' import visualizer from 'rollup-plugin-visualizer' export default defineConfig({ plugins: [ visualizer({ open: true, gzipSize: true, brotliSize: true, }), ], })
-
检查构建输出:
-
运行
vite build
后检查dist
目录 -
使用
vite preview
预览生产构建
-
6. 特殊情况的处理
如果某些代码意外被保留:
-
使用
/*#__PURE__*/
注释:const result = /*#__PURE__*/ expensiveCalculation()
-
动态导入:
// 需要时才加载模块 const module = await import('./moduleA')
Vite 基于 Rollup 的 Tree Shaking 机制非常高效,遵循以上实践可以确保你的生产构建只包含实际使用的代码,从而显著减少包体积。
Webpack 从版本 2 开始支持 Tree Shaking,但需要正确配置才能有效工作。以下是详细实现方法:
1. 基础配置
必须条件
-
使用 ES6 模块语法 (
import
/export
) -
在生产模式 (
mode: 'production'
) 下自动启用 -
避免使用 CommonJS 模块语法 (
require
/module.exports
)
webpack.config.js 基础配置
module.exports = {
mode: 'production', // 生产模式自动启用 Tree Shaking
optimization: {
usedExports: true, // 标记未使用的导出
minimize: true, // 启用代码压缩
concatenateModules: true, // 启用作用域提升(scope hoisting)
}
};
2. 关键配置详解
Babel 配置
确保 Babel 不转换 ES6 模块语法:
{
"presets": [
["@babel/preset-env", {
"modules": false // 保留 ES6 模块语法
}]
]
}
package.json 配置
{
"sideEffects": false,
// 或明确列出有副作用的文件
"sideEffects": [
"*.css",
"*.scss",
"*.vue",
"*.png"
]
}
3. 第三方库优化
按需导入
// 正确 - 按需导入
import { debounce } from 'lodash';
// 避免 - 全量导入
import _ from 'lodash';
使用 ES 模块版本
// 使用 lodash-es 而不是 lodash
import { debounce } from 'lodash-es';
4. 高级优化配置
代码分割 + Tree Shaking
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
排除不需要 Tree Shaking 的文件
module: {
rules: [
{
test: /\.css$/,
sideEffects: true // 标记 CSS 文件有副作用
}
]
}
5. 验证 Tree Shaking 效果
使用分析工具
-
webpack-bundle-analyzer:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; module.exports = { plugins: [ new BundleAnalyzerPlugin() ] }
-
查看未使用导出:
webpack --display-used-exports
手动检查
-
在输出文件中搜索
unused harmony export
-
检查最终打包文件中是否包含预期外的代码
6. 常见问题解决
Tree Shaking 不生效的可能原因
-
使用了 CommonJS 语法:确保全部使用 ES6 模块
-
Babel 转换了模块语法:检查 Babel 配置
"modules": false
-
第三方库不支持:尝试找 ES 模块版本 (如 lodash-es)
-
副作用标记不正确:检查
sideEffects
配置
强制保留某些导出
import { keep } from 'library';
/*@__PURE__*/ keep(); // 使用纯注释标记
通过以上配置,Webpack 可以有效地移除未使用的代码,显著减少最终打包体积。生产环境下 Webpack 的 Tree Shaking 效果通常比开发环境更好,因此务必在生产构建时验证效果。