vue项目打包压缩静态资源---使用compression-webpack-plugin
场景: vue项目打包上线后,资源加载缓慢,用户体验感差。
解决方案: 使用compression-webpack-plugin插件压缩打包的静态资源,优化项目性能。
使用方法
- 下载compression-webpack-plugin
bash
cnpm i compression-webpack-plugin@6.1.1 --save
注意: 这里不能直接下载,需要下载低版本的。直接下载就是最新版的了,vue脚手架暂时不支持最新版的,所以就会报错:TypeError: Cannot read property 'tapPromise' of undefined。我这里下载是指定@6.1.1版本,是可以用的。
- 配置vue.config.js
bash
const CompressionWebpackPlugin = require("compression-webpack-plugin"); // 引入
module.exports = {
configureWebpack: config => {
// 开发环境不配置
if (process.env.NODE_ENV !== 'production') return
// 生产环境才去配置
return {
plugins: [
new CompressionPlugin({
cache: false, // 取消缓存
// filename: "[path][base].gz", // 输出文件名 这种方式是默认的,多个文件压缩就有多个.gz文件,建议使用下方的写法
filename: '[path].gz[query]', // 使得多个.gz文件合并成一个文件,这种方式压缩后的文件少,建议使用
algorithm: 'gzip', // 压缩算法 默认是gzip
test: /\.(js|css)(\?.*)?$/g, // 使用正则给匹配到的文件做压缩,这里是给css、js做压缩
threshold: 10240, // 只处理大于 10KB 的文件
minRatio: 0.8, // 只有压缩率大于0.8的文件才会被处理
//是否删除原有静态资源文件,即只保留压缩后的.gz文件,建议这个置为false,还保留源文件。以防:
// 假如出现访问.gz文件访问不到的时候,还可以访问源文件双重保障
deleteOriginalAssets: false
})
]
}
},
}
- 后端nginx配置
bash
server {
listen 80;
server_name localhost;
location / {
try_files $uri $uri/ /index.html;
root C:/nginx-1.18.0/html/gzip/dist;
index index.html index.htm;
}
location /api/ {
proxy_pass http://localhost:6666/;
}
# 主要是下方的gizp配置哦,直接复制粘贴就可以使用啦,亲测有效哦
gzip on; # 开启gzip压缩
gzip_min_length 10k; # 小于4k的文件不会被压缩,大于4k的文件才会去压缩
gzip_buffers 16 8k; # 处理请求压缩的缓冲区数量和大小,比如8k为单位申请16倍内存空间;使用默认即可,不用修改
gzip_http_version 1.1; # 早期版本http不支持,指定默认兼容,不用修改
gzip_comp_level 2; # gzip 压缩级别,1-9,理论上数字越大压缩的越好,也越占用CPU时间。实际上超过2的再压缩,只能压缩一点点了,但是cpu确是有点浪费。因为2就够用了
# 压缩的文件类型 MIME类型,百度一下,一大把 # css # xml # 识别php # 图片
gzip_types text/plain application/x-javascript application/javascript text/javascript text/css application/xml application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/x-woff font/ttf;
# text # 早期js # js # js的另一种写法 # .eot字体 # woff字体 # ttf字体
gzip_vary on; # 是否在http header中添加Vary: Accept-Encoding,一般情况下建议开启
}
- vue.config.js完整配置项
bash
'use strict'
const path = require('path')
const define = require('./src/utils/define.js')
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin')
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const Version = new Date().getTime()
const Env = process.env.VUE_APP_ENV
function resolve(dir) {
return path.join(__dirname, dir)
}
const name = '空间科学与应用项目论证系统' // page title
const port = process.env.port || process.env.npm_config_port || 3000 // dev port
module.exports = {
// 如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署 https://www.xxx.vip/admin/,则设置 publicPath 为 /admin/。
publicPath: Env == 'production'? '/web/' : '/',
outputDir: 'dist',
assetsDir: 'static',
lintOnSave: false,
productionSourceMap: false,
devServer: {
port: port,
open: false,
overlay: {
warnings: false,
errors: true
},
// 接口转发
proxy: {
'/pmweb': {
target: define.APIURl,
changeOrigin: true,
pathRewrite: {
'^/pmweb': ''
}
}
}
},
configureWebpack: {
name: name,
output: {
filename: `js/[name].js?v=${Version}`,
chunkFilename: `js/[name].js?v=${Version}`,
},
resolve: {
alias: {
'@': resolve('src'),
'static': resolve('static') // 增加这一行代码
}
},
plugins: [
new MonacoWebpackPlugin({
languages: ['javascript', 'css', 'html', 'typescript', 'json', 'java', 'sql']
})
],
},
css: {
extract: {
filename: `css/[name].css?v=${Version}`,
chunkFilename: `css/chunk.[id].css?v=${Version}`,
}
},
chainWebpack(config) {
config.externals({
'echarts': 'echarts'
})
// it can improve the speed of the first screen, it is recommended to turn on preload
config.plugin('preload').tap(() => [{
rel: 'preload',
fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
include: 'initial'
}])
config.plugins.delete('prefetch')
config.module
.rule('svg')
.exclude.add(resolve('src/icons'))
.end()
config.module
.rule('icons')
.test(/\.svg$/)
.include.add(resolve('src/icons'))
.end()
.use('svg-sprite-loader')
.loader('svg-sprite-loader')
.options({
symbolId: 'icon-[name]'
})
.end()
config
.when(process.env.NODE_ENV === 'development',
config => config.devtool('cheap-source-map')
)
config
.when(process.env.NODE_ENV !== 'development',
config => {
config
.plugin('ScriptExtHtmlWebpackPlugin')
.after('html')
.use('script-ext-html-webpack-plugin', [{
inline: /runtime\..*\.js$/
}])
.end()
config
.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
libs: {
name: 'chunk-libs',
test: /[\\/]node_modules[\\/]/,
priority: 10,
chunks: 'initial' // only package third parties that are initially dependent
},
elementUI: {
name: 'chunk-elementUI', // split elementUI into a single package
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
},
commons: {
name: 'chunk-commons',
test: resolve('src/components'), // can customize your rules
minChunks: 3, // minimum common number
priority: 5,
reuseExistingChunk: true
}
}
})
config.optimization.runtimeChunk('single')
config.plugin("compression").use(CompressionWebpackPlugin, [
{
cache: false, // 取消缓存
filename: "[path][base].gz[query]", // 输出文件名
algorithm: "gzip", // 压缩算法
// test: /\.(js|css)$/, // 匹配需要压缩的文件类型,使用该种方式js文件夹下js不会被压缩
test: /\.(js|css)(\?.*)?$/g,
threshold: 10240, // 只处理大于 10KB 的文件
minRatio: 0.8, // 只有压缩率大于0.8的文件才会被处理
deleteOriginalAssets: false, // 是否删除原始文件
},
]);
}
)
}
}
参考文章https://zhuanlan.zhihu.com/p/530959154