接手了一个项目,打包完index.js居然有十几M,本地还好,部署线上以后
网速快的情况可能十几秒就能加载完,网速慢的话就会出现
“喂,你们项目挂了,白屏一直。。 哦!! 有了有了有了 挂了哈。”
慢到一定境界了。
查询了很多资料,发现原来webpack也不是那么那么的晦涩难懂,真用到的时候,
学学 用用还挺好玩。
gzip on;
gzip_disable "msie6";
gzip_static on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 4 32k;
gzip_http_version 1.1;
gzip_min_length 1k;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg
image/gif image/png;
具体每一块代表的意思 我这里粘一下,但是其实我这段代码 可以直接粘过去用。
l gzip:决定是否开启gzip模块。
l gzip_disable:(IE5.5和IE6 SP1使用msie6参数来禁止gzip压缩)。指定哪些不需要gzip压缩的浏览器(将和User-Agents进行匹配)。
l gzip_vary:增加响应头”Vary: Accept-Encoding”。
l gzip_proxied:Nginx做为反向代理的时候启用:·
off –关闭所有的代理结果数据压缩· expired –如果header中包含”
Expires”头信息,启用压缩· no-cache –如果header中包含”Cache-Control:no-cache”头信息,启用压缩·
no-store –如果header中包含”Cache-Control:no-store”头信息,启用压缩·
private –如果header中包含”Cache-Control:private”头信息,启用压缩·
no_last_modified –启用压缩,如果header中包含”Last_Modified”头信息,启用压缩·
no_etag –启用压缩,如果header中包含“ETag”头信息,启用压缩·
auth –启用压缩,如果header中包含“Authorization”头信息,启用压缩·
any –无条件压缩所有结果数据
l gzip_types:这个参数是指设置需要压缩的MIME类型,如果不在设置类型范围内的请求不进行压缩。lgzip_comp_level:设置gzip压缩等级,等级越压缩速度越快文件压缩比越小,反之速度越慢文件压缩比越大。范围是1-9,根据需求设定。
l gzip_buffers:设置用于处理请求压缩的缓冲区数量和大小。比如32 4K表示按照内存页(one memory page)大小以4K为单位(即一个系统中内存页为4K),申请32倍的内存空间。建议此项不设置,使用默认值。
l gzip_http_version:用于识别http协议的版本,早期的浏览器不支持gzip压缩,用户会看到乱码,所以为了支持前期版本加了此选项。默认在http/1.0的协议下不开启gzip压缩。
在自己的nginx服务器的server上方加上gzip的这些配置,重启nginx就可以了。
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
然后再configureWebpack中,写入
configureWebpack: (config) => {
if (process.env.NODE_ENV === 'production') {
// 打包后每个文件的内容和大小
config.plugins.push(new BundleAnalyzerPlugin());
} else {
// 开发环境
}
},
提到这里的process.env.NODE_ENV,这里多讲一点,从if判断句,能很容易的看出,这是
说在生产环境下启用,这里的打包时所有配置环境是由,
.env.development
.env.production
来进行配置的。
当你对项目打包的时候,其实是运行了 npm run build
在package.json中有一句话,
scripts中build项 build,如果未指定mode,则默认去执行.env.production
如果指定mode,那么写法如下:
"build:outter": "vue-cli-service build --mode outterProduction",
指定mode为outterProduction,则会默认去执行.env.outterProduction
以.env.production为例,在文件中声明设置NODE_ENV和VUE_APP_NODE_ENV的赋值,则在
configureWebpack中可利用process.env.NODE_ENV来判断当前打包环境是否为生产环境。
继续说 webpack-bundle-analyzer,加上上述的语句后,打包会出现性能分析界面:
可查看那些文件过大,打包总时长等信息。
<script src="https://cdn.bootcss.com/vue/2.6.11/vue.min.js"></script>
<script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script>
然后在chainWebpack中 加入下述语句 可在打包的时候,忽略node_modules中,这些包的依赖
config.externals({
vue: 'Vue',
vuex: 'Vuex',
'vue-router': 'VueRouter',
});
// 分包
config.optimization.splitChunks({
cacheGroups: { // 缓存组,将所有加载模块放在缓存里面一起分割打包
vendors: { // 自定义打包模块
name: 'chunk-vendors', // 打包后的文件名
test: /[\\/]node_modules[\\/]/, // 匹配对应文件
priority: 1, // 优先级,先打包到哪个组里面,值越大,优先级越高
// initial: 对于匹配文件,非动态模块打包进该vendor,动态模块优化打包
// async: 对于匹配文件,动态模块打包进该vendor,非动态模块不进行优化打包
// all: 匹配文件无论是否动态模块,都打包进该vendor
chunks: 'initial',
enforce: true, // true/false。为true时,忽略minSize,minChunks
reuseExistingChunk: true,
},
base: {
name: 'chunk-base',
// test: /[\\/]node_modules[\\/](element-ui|vue)[\\/]/,
test: /[\\/]node_modules[\\/](element-ui)[\\/]/,
priority: 2,
chunks: 'initial',
enforce: true,
reuseExistingChunk: true,
},
},
});
```
通过将index.js中依赖的大包弄出来,形成单独的js来实现分包处理,使主index从根源上变小。
SplitChunks插件配置选项:
chunks选项,决定要提取那些模块。
默认是async:只提取异步加载的模块出来打包到一个文件中。
异步加载的模块:通过import('xxx')或require(['xxx'],() =>{})加载的模块。
initial:提取同步加载和异步加载模块,如果xxx在项目中异步加载了,也同步加载了,那么xxx这个模块会被提取两次,分别打包到不同的文件中。
同步加载的模块:通过 import xxx或require('xxx')加载的模块。
all:不管异步加载还是同步加载的模块都提取出来,打包到一个文件中。
minSize选项:规定被提取的模块在压缩前的大小最小值,单位为字节,默认为30000,只有超过了30000字节才会被提取。
maxSize选项:把提取出来的模块打包生成的文件大小不能超过maxSize值,如果超过了,要对其进行分割并打包生成新的文件。单位为字节,默认为0,表示不限制大小。
minChunks选项:表示要被提取的模块最小被引用次数,引用次数超过或等于minChunks值,才能被提取。
maxAsyncRequests选项:最大的按需(异步)加载次数,默认为 6。
maxInitialRequests选项:打包后的入口文件加载时,还能同时加载js文件的数量(包括入口文件),默认为4。
先说一下优先级 maxInitialRequests / maxAsyncRequests ``javascript
module.exports = {
pages: {
index: {
entry: 'src/main.js',
template: 'public/index.html',
filename: 'index.html',
chunks: ['chunk-vendors', 'chunk-base', 'index'],
}
},
}
其实关于分包还有好多讲究,我还没有细细研究,说白了 水平越高的前端开发工程师,分包会越细致,效果也会越好。
5.懒加载(异步组件)
这个大家都知道
在开发的时候,需要合理的划分各模块,做到首屏加载的时候只读取必要的模块,其他模块在需要的时候才从服务器加载。通过这种异步加载组件的方式,在打包的时候就不会把相关的组件打包到首屏相关的js中,可以减少首屏渲染相关文件的大小。
形如:
() => import('@/views/abc.vue')
不管是路由 还是页面,都可以用这种形式。
大致这一通下来,首屏加载能提升60%-70%,甚至更高。
我的页面从最初十几秒优化下来以后变成3-4秒就可以进入,我猜还有进步空间,
大家一起发掘吧。fighting~