在 Vue CLI 项目中进行构建优化,是前端性能提升的重要手段。它涉及到 Webpack 配置、代码分包、懒加载、依赖优化、图片压缩等多个方面。
🧱 基础构建优化
设置生产环境变量
NODE_ENV=production
Vue CLI 会自动在 npm run build 时开启以下优化:
- 压缩 JS / CSS
- 移除 console 和 debugger
- 自动分离 vendor 文件(依赖包)
开启 gzip 压缩
使用 compression-webpack-plugin:
npm install compression-webpack-plugin -D
// vue.config.js
const CompressionWebpackPlugin = require('compression-webpack-plugin')
module.exports = {
configureWebpack: {
plugins: [
new CompressionWebpackPlugin({
algorithm: 'gzip',
test: /\.(js|css|html|svg)$/,
threshold: 10240,
minRatio: 0.8
})
]
}
}
去除 map 文件
module.exports = {
productionSourceMap: false
}
📦 代码层优化
路由懒加载(代码分割)
const Home = () => import(‘@/views/Home.vue’)
打包时,每个路由页面都会单独分包。
使用 CDN 加载库文件
把 Vue、Vuex、Vue Router 等用 CDN 引入:
// vue.config.js
module.exports = {
configureWebpack: {
externals: {
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex'
}
}
}
然后在 public/index.html 中引入 CDN:
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
Tree Shaking & 按需引入
避免全量引入组件库,例如:
// ❌ 错误
import ElementPlus from 'element-plus'
app.use(ElementPlus)
// ✅ 推荐
import { ElButton, ElSelect } from 'element-plus'
app.use(ElButton).use(ElSelect)
🧠 Webpack 配置层优化(Vue CLI 内部使用 Webpack)
使用缓存
// vue.config.js
module.exports = {
chainWebpack: config => {
config.cache(true)
}
}
分析包体积
npm install webpack-bundle-analyzer -D
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
configureWebpack: {
plugins: [new BundleAnalyzerPlugin()]
}
}
🖼 资源层优化
图片压缩
使用 image-webpack-loader:
npm install image-webpack-loader -D
module.exports = {
chainWebpack: config => {
config.module
.rule('images')
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
mozjpeg: { progressive: true, quality: 65 },
pngquant: { quality: [0.65, 0.90], speed: 4 }
})
}
}
图片懒加载
npm install vue-lazyload
import VueLazyload from 'vue-lazyload'
app.use(VueLazyload, { loading: 'loading.png' })
🧊 缓存优化(浏览器缓存策略)
文件名加 hash(默认支持)
Vue CLI 打包后文件名默认带有 [hash],有助于浏览器缓存:
app.234d7f.js
静态资源持久缓存(使用 CDN + Cache-Control)
在 nginx 或服务端配置:
Cache-Control: max-age=31536000
✅ 总结表格
优化项 | 方法 | 效果 |
---|---|---|
路由懒加载 | import() 异步组件 | 减少初始加载体积 |
CDN 加载依赖 | externals + script 标签 | 减少 bundle 体积 |
gzip 压缩 | compression-webpack-plugin | 减少传输体积 |
移除 console | terser 插件自动处理 | 减少无用代码 |
图片压缩 | image-webpack-loader | 优化图片大小 |
分析构建 | webpack-bundle-analyzer | 找出最大依赖 |
map 文件移除 | productionSourceMap: false | 避免泄露源代码 |
资源缓存 | hash 文件名 + Cache-Control | 浏览器缓存优化 |
示例
以下是一个Vue CLI 项目中的完整优化配置文件 vue.config.js,包含以下功能:
• 关闭 source map
• 使用 CDN 外部引入 Vue、Vuex、Vue Router
• gzip 压缩
• 图片压缩
• 移除 console/debugger
• 打包分析器(可选)
✅ vue.config.js
const CompressionWebpackPlugin = require('compression-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
productionSourceMap: false, // 关闭 source map
configureWebpack: config => {
const plugins = []
// gzip 压缩
if (isProd) {
plugins.push(
new CompressionWebpackPlugin({
algorithm: 'gzip',
test: /\.(js|css|html|svg)$/,
threshold: 10240,
minRatio: 0.8
})
)
}
// CDN 依赖(在 index.html 中引入)
config.externals = isProd
? {
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex'
}
: {}
config.plugins = [...config.plugins, ...plugins]
},
chainWebpack: config => {
// 图片压缩
config.module
.rule('images')
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({
mozjpeg: { progressive: true, quality: 65 },
optipng: { enabled: false },
pngquant: { quality: [0.65, 0.9], speed: 4 },
gifsicle: { interlaced: false },
webp: { quality: 75 }
})
// 打包分析(按需启用)
if (process.env.ANALYZE) {
config
.plugin('webpack-bundle-analyzer')
.use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
}
},
// 移除 console/debugger(可选)
configureWebpack: config => {
if (isProd) {
config.optimization = {
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
},
extractComments: false
})
]
}
}
}
}
✅ 还需要在 public/index.html 中引入 CDN(用于生产环境)
<!-- public/index.html -->
<head>
<title>Vue App</title>
<% if (process.env.NODE_ENV === 'production') { %>
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuex@4.1.0/dist/vuex.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router@4.1.0/dist/vue-router.global.prod.js"></script>
<% } %>
</head>