vue 开发中必备的 cli 配置
本文整理了一些 vue 开发中常用 vue-cli 配置,使用的 vue-cli 版本为 3.11.0,主要内容包括:移除preload 与prefetch使用webpack-bundle-analyzer 做打包分析使用terser-webpack-plugin 清除 console.log使用compression-webpack-plugin 开启gzip 压缩配置使用CDN 方式引入资源库
本文整理了一些 vue 开发中常用 vue-cli 配置,使用的 vue-cli 版本为 3.11.0,主要内容包括:
- 移除 preload 与 prefetch
- 使用 webpack-bundle-analyzer 做打包分析
- 使用 terser-webpack-plugin 清除 console.log
- 使用 compression-webpack-plugin 开启 gzip 压缩
- 配置使用 CDN 方式引入资源库
- 自定义打包的 css/js/图片 文件名和路径
- 压缩图片
文末给出了完整的 vue.config.js 配置。
1.移除 preload(预载) 与 prefetch (预取)
vue 脚手架默认开启了 preload 与 prefetch,当我们项目很大时,这个就成了首屏加载的最大元凶了。
先简单了解一下 preload 与 prefetch。
- preload 与 prefetch 都是一种资源预加载机制;
- preload 是预先加载资源,但并不执行,只有需要时才执行它;
- prefetch 是意图预获取一些资源,以备下一个导航/页面使用;
- preload 的优先级高于 prefetch。
更多请参考 MDN:通过rel="preload"进行内容预加载
看看关闭 preload 与 prefetch 之前的效果:
这里我标注了 4 个部分,
- 1 代表当前页面的 css/js 资源;
- 2 代表 UI 库等资源的 css 与 main.js 中自定义的 css
- 3 代表 main.js 中自定的 js 与 UI 库等资源的 js
- 4 代表其他页面的资源
其中,2 和 3 都使用了 preload,4 使用了 prefetch。当应用的页面非常多时,会导致 4 的部分增加,以至于首屏加载的速度降低。
关闭 preload 与 prefetch
chainWebpack: config => {
// 移除 preload(预载) 插件
config.plugins.delete('preload')
// 移除 prefetch(预取) 插件
config.plugins.delete('prefetch')
}
关闭后的效果:
关闭前的首屏速度 11s,关闭后 1~2 秒,速度加快 10 倍...
2.使用 webpack-bundle-analyzer 做打包分析
脚手架中默认就包含有 webpack-bundle-analyzer 插件,所以直接使用即可
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
chainWebpack: config => {
// npm run analyzer 时才开启
if (process.env.npm_config_report) {
config
.plugin('webpack-bundle-analyzer')
.use(BundleAnalyzerPlugin)
}
}
}
然后再配置 package.json
"scripts": {
"analyzer": "cross-env NODE_ENV=production npm_config_report=true npm run build"
},
在 cmd 中执行
npm run analyzer
页面效果(这里只展示左侧侧边栏)
3.使用 terser-webpack-plugin 清除 console.log
开发过程中我们往往需要 console.log 进行调试,调试完后一般也会删除或注释掉,但难免有时会忘记,所以可以使用 terser-webpack-plugin 来清除 console.log。
先安装依赖
npm install terser-webpack-plugin --save-dev
然后配置
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
configureWebpack: config => {
// 生产环境下清除 console.log
if (process.env.NODE_ENV === 'production') {
return {
optimization: {
minimizer: [
new TerserPlugin({
sourceMap: false,
terserOptions: {
compress: {
drop_console: true
}
}
})
]
}
}
}
}
}
4.使用 compression-webpack-plugin 开启 gzip 压缩
开启 gzip 压缩也能极大加快页面加载速度。
先安装依赖
npm install compression-webpack-plugin --save-dev
然后配置
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
configureWebpack: config => {
config.plugins = [
...config.plugins,
// 开启 gzip 压缩
new CompressionPlugin({
filename: '[path][base].gz',
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8
})
]
}
}
压缩后会生成相应的 gz 文件
可以看见,压缩效果还是很明显的。
只有前端配置 gzip 是不够的,如果你使用了 nginx,还需对其进行配置
http {
gzip on; # 开启 gzip 压缩
gzip_static on; # 若存在静态 gz 文件,则使用该文件
gzip_min_length 10k; # 设置允许压缩的页面最小字节数
gzip_buffers 16 8k; # 设置用于处理请求压缩的缓冲区数量和大小
gzip_comp_level 1; # 设置压缩级别 1-9,数字越大,压缩后的大小越小,也越占用CPU,花费时间越长
# 对特定的 MIME 类型生效, 其中'text/html’被系统强制启用
gzip_types application/javascript text/css font/ttf font/x-woff;
gzip_vary on; # 是否在 http header中 添加 Vary:Accept-Encoding, on | off
gzip_http_version 1.1; # 在 http/1.1 的协议下不开启压缩
}
gzip 相关配置说明可参考:Nginx gzip参数详解及常见问题
如果资源响应头中出现 Content-Encoding: gzip 则代表配置成功
同时,也能通过比较资源的实际大小和请求大小是否一致来判断是否开启了压缩。
5.配置使用 CDN 方式引入资源库
先完成配置:
configureWebpack: config => {
config.resolve = {
// 使用 CDN 的包不用打包到文件中
externals: {
// 这里的 element-ui 是 import xx from yy 中的 yy 包名。ELEMENT 是文件导出的全局变量名字
'element-ui': 'ELEMENT',
},
},
},
chainWebpack: config => {
// 添加 CDN 参数到 htmlWebpackPlugin 配置中
config.plugin('html').tap(args => {
args[0].cdn = {
js: [
'https://xx.com/CDN/js/index-element-ui@2.13.0.js',
],
css: [
'https://xx.com/CDN/css/element-ui2.13.0/index.css',
],
};
return args;
});
},
然后在 index.html 中挂载 CDN:
<!DOCTYPE html>
<html lang="zh">
<head>
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style">
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet">
<% } %>
<!-- 使用 CDN 加速的 JS 文件,配置在 vue.config.js 下 -->
<% for (var i in htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>" type="text/javascript"></script>
<% } %>
</head>
<body>
<div id="app"></div>
</body>
</html>
如果公司没有自己的 CDN,这里推荐两个比较好的:BootCDN 与 cdnjs 。
当然,使用他人的 CDN 你就要考虑安全和稳定性了,要是 CDN 突然挂了(可能性比较小)就很伤。
6.自定义打包的 css/js/图片 文件名和路径
如果你想自定义打包文件名的话,可以考虑进行以下配置。
const appVersion = require('./package.json').version;
const timestamp = new Date().getTime(); // 时间戳
module.exports = {
css: {
extract: {
// 自定义打包的 css 文件名和路径
chunkFilename: `assets/css/[name].[${appVersion}-${timestamp}].css`
},
},
chainWebpack: config => {
// 修改图片打包配置
config.module
.rule('images')
.test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
.use('url-loader')
.loader('url-loader')
.tap(options => {
// 修改它的选项...
options.fallback.options.name = `assets/img/[name].[${appVersion}-${timestamp}].[ext]`; // 修改文件名
// 这是字节(Byte)限制,1KB = 1024Byte,当图片的大小小于4KB(默认值),则会被转为base64格式,打包进js文件,
// 大于4KB,则会被打包进 img 文件夹,供链接请求获取。
options.limit = 1024 * 4;
return options
})
},
configureWebpack: config => {
// 自定义打包的 js 文件名和路径
config.output.chunkFilename = `assets/js/[name].[${appVersion}-${timestamp}].js`
}
}
注:[name] 就是默认的 webpackChunkName。
大致效果如下:
7.压缩图片
如果需要对图片进行压缩的话可以使用以下配置。
先安装依赖
npm install image-webpack-loader --save-dev
然后配置
chainWebpack: config => {
// 压缩图片
config.module
.rule('images')
.use('imageWebpackLoader')
.loader('image-webpack-loader')
.options({
disable: process.env.NODE_ENV === 'development', // 开发环境下禁止压缩
gifsicle: {
interlaced: false
}
})
}
但我一般不用这个压缩,这里推荐一个在线压缩网站:TinyPNG – Compress WebP, PNG and JPEG images intelligently
结尾:完整的 vue.config.js 配置
const path = require('path');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const TerserPlugin = require('terser-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
// 是否是开发环境 development | production
const isDevlopment = process.env.NODE_ENV === 'development';
// const appVersion = require('./package.json').version;
// const timestamp = new Date().getTime();
function resolve (dir) {
return path.join(__dirname, dir)
}
module.exports = {
publicPath: './', // 根路径
outputDir: 'dist', // 构建输出目录
assetsDir: 'assets', // 静态资源目录
lintOnSave: false, // 是否开启eslint保存检测,有效值:true || false || 'error'
devServer: {
open: false, // 项目运行后是否自动打开浏览器
host: '0.0.0.0', // 既可localhost,也可ip访问
port: 8081,
https: false,
hotOnly: false, // 热更新
},
productionSourceMap: false, // 生产环境下关闭 SourceMap
css: {
// extract: {
// // 自定义打包的 css 文件名和路径
// chunkFilename: `assets/css/[name].[${appVersion}-${timestamp}].css`
// },
sourceMap: isDevlopment // 开发环境下开启方便调试样式
},
chainWebpack: config => {
// 移除 preload(预载) 插件
config.plugins.delete('preload')
// 移除 prefetch(预取) 插件
config.plugins.delete('prefetch')
// npm run analyzer 时才开启
if (process.env.npm_config_report) {
config
.plugin('webpack-bundle-analyzer')
.use(BundleAnalyzerPlugin) // 分析项目文件大小的插件
}
// 添加 CDN 参数到 htmlWebpackPlugin 配置中
config.plugin('html').tap(args => {
args[0].cdn = {
js: [
'https://xx.com/CDN/js/index-element-ui@2.13.0.js',
],
css: [
'https://xx.com/CDN/css/element-ui2.13.0/index.css',
],
}
return args
})
// 压缩图片
// config.module
// .rule('images')
// .use('imageWebpackLoader')
// .loader('image-webpack-loader')
// .options({
// disable: isDevlopment, // 开发环境下禁止压缩
// gifsicle: {
// interlaced: false
// }
// })
// 修改图片打包配置
// config.module
// .rule('images')
// .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
// .use('url-loader')
// .loader('url-loader')
// .tap(options => {
// // 修改它的选项...
// options.fallback.options.name = `assets/img/[name].[${appVersion}-${timestamp}].[ext]`; // 修改文件名
// // 这是字节(Byte)限制,1KB = 1024Byte,当图片的大小小于4KB(默认值),则会被转为base64格式,打包进js文件,
// // 大于4KB,则会被打包进 img 文件夹,供链接请求获取。
// options.limit = 1024 * 4;
// return options
// })
},
configureWebpack: config => {
// 自定义打包的 js 文件名和路径
// config.output.chunkFilename = `assets/js/[name].[${appVersion}-${timestamp}].js`
config.resolve = {
extensions: ['.js', '.vue', '.json', '.css'],
// 配置路径别名
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'api': resolve('src/api'),
'css': resolve('src/assets/css')
},
// 使用 CDN 的包不用打包到文件中
externals: {
// 这里的 element-ui 是 import xx from yy 中的 yy 包名。ELEMENT 是文件导出的全局变量名字
'element-ui': 'ELEMENT',
},
},
config.plugins = [
...config.plugins,
// 开启 gzip 压缩
new CompressionPlugin({
filename: '[path][base].gz',
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8
})
]
// 生产环境下
if (!isDevlopment) {
return {
optimization: {
minimizer: [
new TerserPlugin({
sourceMap: false,
terserOptions: {
compress: {
drop_console: true // 生产环境下清除 console.log
}
}
})
]
}
}
}
}
};
更多推荐
所有评论(0)