今天前端妹子让我优化项目,想无,一大早来到公司,老大已经到了,我耳机听着谢霆锋的歌‘活着 via’,庆幸活着真好,想无,过了国庆心情是真的很好啊,歇息歇得我快废掉了,赶紧打代码,不打代码出去浪对钱不好,咱们还是不泡妞了,好好把钱用来投资理财吧,泡妞太花钱了,一天可以花你一个月的饭钱啊,心痛啊。
一个 qq 消息扔过来,之前有看过 webpack,只看过一点点,没有实践过,过了不久,有扔过来一条消息,一个链接,全都是英文的,哇靠,不知道我英文很好?哈哈,不过外国的文章是真的牛逼啊。
4 Ways To Boost Your Vue.js App With Webpackvuejsdevelopers.com
我冷静下来仔细想想,不能直接上来就干,我们得有目的性的工作,首先我们得知道哪些地方是需要我们去优化的,哪些地方有影响到首屏加载的效果的。
所以,我想到有没有什么插件是可以直接生成一个 report 优化报告的东西,还真有
webpack-bundle-analyzer
这个分析插件
最近基础的用法如下:
安装
# NPM npm install --save-dev webpack-bundle-analyzer
# Yarn
yarn add -D webpack-bundle-analyzer
基本使用方法
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [new BundleAnalyzerPlugin()
]
}
配置:
使用
参数说明:
{
analyzerMode:One of: server, static, disabled,analyzerHost {String} Default: 127.0.0.1. Host that will be used in server mode to start HTTP server.
analyzerPort {Number} or auto Default: 8888. Port that will be used in server mode to start HTTP server.
openAnalyzer {Boolean} Default: true. Automatically open report in default browser.
generateStatsFile {Boolean} Default: false. If true, webpack stats JSON file will be generated in bundle output directory
statsFilename {String} Default: stats.json. Name of webpack stats JSON file that will be generated if generateStatsFile is true. It can be either an absolute path or a path relative to a bundle output directory (which is output.path in webpack config).
statsOptions null or {Object} Default: null. Options for stats.toJson() method. For example you can exclude sources of your modules from stats file with source: false option. See more options here.}
原理:如下:
读取输出文件夹(通常是 dist)中的 stats.json 文件,把该文件可视化展现的插件。便于直观地比较各个 bundle 文件的大小,以达到优化性能的目的。
两种构建模式
1 构建完自动打开浏览器:默认端口为 8888
new BundleAnalyzerPlugin({analyzerMode: 'server', generateStatsFile: true, statsOptions: { source: false} })
2 使用 package.json 文件配置启动命令
new BundleAnalyzerPlugin({
analyzerMode: 'disabled',
generateStatsFile: true,
statsOptions: {source: false}
})
在 package.json 的 scripts 字段中加入
"bundle-report": "webpack-bundle-analyzer --port 8123 dist/stats.json"
(3)命令行中键入命令
npm run bundle-report
浏览器自动打开分析页面:localhost:8123
我们可以从哪几个方面入手去优化,我们抛开我们自己的项目来聊聊一般我们如何优化项目,
1 第一个肯定是压缩 js 文件,和压缩 css 文件
这个 webpack vue-cli3 已经自动给我们做好了,我们可以不必担心
2 去除 mapSource 文件
map 文件是 js 文件压缩后,文件的变量名替换对应、变量所在位置等原信息数据文件。个人理解是:对 js 压缩过程的记录,如浏览器支持,可以通过 map 文件还原文件到未压缩之前。
3 图片压缩
npm install image-webpack-loader --save-dev
用法:
// 压缩图片
chainWebpack: config => {
config.module
.rule('images')
.use('image-webpack-loader')
.loader('image-webpack-loader')
.options({bypassOnDebug: true})
.end()},
这段代码做了两件事:一是压缩,二是转 Base64
可以发现在 dist/img 下面的图片少了一部分,原因是:不超过 4096 字节会被转换成 Base64 编码, 用 require 引用的也会被转成和 base64,超出这个限制则会被打包在 img 文件夹下。
我们使用是如下:
4. 公共代码抽离
configureWebpack: () => ({
optimization: {
splitChunks: {
cacheGroups: {
vendor:{
chunks:"all",
test: /node_modules/,
name:"vendor",
minChunks: 1,
maxInitialRequests: 5,
minSize: 0,
priority:100,
},
common: {
chunks:"all",
test:/[\\/]src[\\/]js[\\/]/,
name: "common",
minChunks: 2,
maxInitialRequests: 5,
minSize: 0,
priority:60
},
styles: {
name: 'styles',
test: /\.(sa|sc|c)ss$/,
chunks: 'all',
enforce: true,
},
runtimeChunk: {name: 'manifest'}
}
}
}
}),
但是实际上 vue-cli3 已经做了代码抽离了,或许不是我们需要的,我们可以做以上代码更改。
5.GZip
asset size limit: The following asset(s) exceed the recommended size limit (244 KiB). This can impact web performance.
意思是这些文件大于了 244kb,可以使用 Gzip 在压缩一次
npm i -D compression-webpack-plugin
plugins:[
new CompressionWebpackPlugin({filename: '[path].gz[query]',
algorithm: 'gzip',
test: /\.js$|\.html$|\.json$|\.css/,
threshold: 0, // 只有大小大于该值的资源会被处理
minRatio:0.8, // 只有压缩率小于这个值的资源才会被处理
deleteOriginalAssets: true // 删除原文件
})
],
但是实际上我们不需要在代码层面进行压缩,其实我们可以在部署项目的时候开启服务器的 gzip 压缩。
当前我们项目最主要的就是 element-ui 加 echarts 加 moment.js
这三个地方是最主要需要优化的地方,我们从分析结构图得知,moment.js 占用很大体积,主要是由于他的 i18n 文件占用的。所以我们在打包的时候,不需要打包 i18n 文件,只需要 js 文件就行了,我们在 vue.config.js 做了一下处理,
至于 element-ui 的时候,我们可以使用按需加载,当前项目是直接在 main.js 全局引入 element-ui 的所需要的组件,但是这样有一个坏处就是,首屏加载的时候,我们会把所有的东西都加载一遍,而且我们的项目是二次封装了 element-ui 组件的,这样就会导致
element-ui 的依赖文件被引入了两次,所以我们要做的就是把在 main.js 中引入的组件都迁移到各 component 组件下的各个文件
至于 echarts 也是很庞大的,就可占用掉 3 M 多的带宽了。所以这是一个大问题,也是不要在 main.js 里面引入,不做全局引入,在各自使用到的当前项目的页面再去引入,这样可以做到按需加载,就不会占用首屏太多时间了。
最终优化下来是