大家好,我是猫小白,本文基于
vue2
,全文浏览大概须要 3 分钟。
谈到 webpack 优化大部分人可能都看腻了,无非就那几招嘛,我之前也是看过许多相似的文章,但都没有本人真正上手过,上面是我用公司的我的项目实在操练下来的,首屏加载速度晋升很大(刷刷的),心愿能帮到你。
废话不多说,先看看比照成绩!
类型 | 优化前 | 优化后 |
---|---|---|
js 文件大小 | 24MB | 3MB |
主页首屏显示 | 9s | 1s |
这几乎太夸大了,晋升了 8 倍?能够设想以前是多慢,要等半天啊。蛮王 这个真男人都开大 2 次了~
能够看到,优化前后首屏加载速度有质的晋升,之前始终想优化咱们我的项目的首屏加载工夫,有缓存还好,没有缓存屏幕白屏都要期待 7、8s。特地是有的客户第一次关上这个零碎,那 7、8 秒犹如过了一个世纪,十分难堪。那么我做了那些惯例操作呢?
1. 生产环境敞开productionSourceMap
、css sourceMap
家喻户晓,SourceMap
就是当页面呈现某些谬误,可能定位到具体的某一行代码,SourceMap
就是帮你建设这个映射关系的,不便代码调试。在生产环境中咱们齐全没必要开启这个性能(谁在生产环境调试代码?不会是你吧)
如下配置:
const isProduction = process.env.NODE_ENV === 'production' // 判断是否是生产环境
module.exports = {
productionSourceMap: !isProduction, // 敞开生产环境下的 SourceMap 映射文件
css: {
sourceMap: !isProduction, // css sourceMap 配置
loaderOptions: {... 其它代码}
},
... 其它代码
}
此时再npm run build
打包,就会发现速度快了很多,体积霎时只有几兆了!
2. 剖析大文件,找出内鬼
装置 npm install webpack-bundle-analyzer -D
插件,打包后会生产一个本地服务,分明的展现打包文件的蕴含关系和大小。
vue.config.js
配置:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
... 其它
configureWebpack: [
plugins: [new BundleAnalyzerPlugin() // 剖析打包大小应用默认配置
]
},
... 其它
}
自动弹出一个服务,清晰的展现打包后 js 的文件大小:
通过图中能够发现:
- element-ui 和 ant-design 占了近 1 / 4 的大小:
1.53MB
。 - exceljs 也是个大货色有:
1.3MB
- echarts.js 文件也靠近
1MB
- moment.js 也有
700KB
打包后 js 文件一共就 5MB,这五个哥们就占了 4M 左右。不剖析好还,一剖析吓得够呛~
不要虚!找到刺了,一个一个来拔掉就好了。置信我拔掉的过程是很爽的。
一个一个解决,拔刺
1. 把必须要用的第三方 js 通过 cdn 的形式援用
剖析发现,elementui、echarts
是必须应用的,打包又耗时且页面加载也较慢得很。能够通过 cdn
间接引入,不便且速度快。
1.element-ui
是咱们我的项目用的次要框架,所以这个必定是少不了,然而我的项目外面 ant-design
为什么会存在呢,原来是发现有个页面应用了 antd
的进度条组件,因为 elementui
的进度条不太好看。然而没想到这样把整个 antd
都导进来了。
计划:
- 舍弃
antd
组件,本人去找一个相似的vue
插件或者罗唆本人实现一个。(这个办法短时间无奈实现,且不想去动以前代码,暂不思考) - 应用
antd
局部加载。只加载想要的进度条组件,能够缩小文件体积(这个办法简略粗犷,就是就义一些文件大小)。
咱们应用计划2,依据 antd 官网的文档配置局部组件的引入。
装置 npm install babel-plugin-import -D
1 main.js
导入须要的组件 Step
import {Steps} from 'ant-design-vue';
Vue.component(Steps.name, Steps);
Vue.component(Steps.Step.name, Steps.Step);
2 babel.config.js
加上配置:
module.exports = {
presets: ['@vue/cli-plugin-babel/preset'],
// 以下是按需加载的配置 ++++
plugins: [
[
"import",
{
libraryName: "ant-design-vue",
libraryDirectory: "es",
style: true
}
]
]
}
此时再剖析,antd
曾经小了很多。
2. 应用 cdn 加载第三方 js。
咱们我的项目外面第三方 js
很多,有些打包下来会很大,而且加载速度较慢。咱们把这些 js 分离出来,通过 cdn
的形式在 html
中的 script
标签中间接应用,一方面缩小打包体积,一方面进步了加载速度。
这里举荐一个收费的 cdn
: BootCDN。也能够应用本人购买的付费cdn
服务,咱们到网站搜寻本人我的项目须要的js
。例如:vue
留神,肯定要抉择本人我的项目对应的版本,否则会呈现各种奇怪的问题
我的我的项目应用的是 "vue": "^2.6.12",
(package.json)
第一步:配置 vue.config.js
,让webpack
不打包这些 js,而是通过 script
标签退出。
const isProduction = process.env.NODE_ENV === 'production' // 判断是否是生产环境
// 正式环境不打包公共 js
let externals = {}
// 贮存 cdn 的文件
let cdn = {
css: ['https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.0/theme-chalk/index.min.css' // element-ui css 样式表],
js: []}
// 正式环境才须要
if (isProduction) {
externals = { // 排除打包的 js
vue: 'Vue',
'element-ui': 'ELEMENT',
echarts: 'echarts',
}
cdn.js = [
'https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js', // vuejs
'https://cdn.bootcdn.net/ajax/libs/element-ui/2.6.0/index.js', // element-ui js
'https://cdn.bootcdn.net/ajax/libs/element-ui/2.6.0/locale/zh-CN.min.js',
'https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.min.js',
]
}
module.exports = {
//... 其它配置
configureWebpack: {
// 罕用的公共 js 排除掉,不打包 而是在 index 增加 cdn,externals,
//... 其它配置
},
chainWebpack: config => {
//... 其它配置
// 注入 cdn 变量 (打包时会执行)
config.plugin('html').tap(args => {args[0].cdn = cdn // 配置 cdn 给插件
return args
})
}
//... 其它配置
}
第二步:html 模板中退出定义好的 cdn 变量应用的代码
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>web</title>
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!-- 引入款式 -->
<% for(var css of htmlWebpackPlugin.options.cdn.css) { %>
<link rel="stylesheet" href="<%=css%>" >
<% } %>
<!-- 引入 JS -->
<% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%=js%>"></script>
<% } %>
</head>
<body style="font-size:14px">
<div id="app"></div>
</body>
</html>
能够发现 cdn.js
中,我把 vue、echarts、element-ui
这三个大头退出了。在 externals
对象中左侧是 npm
包的名称,右侧是在代码中裸露的全局变量。留神 element-ui
对应的是 ELEMENT
。
没有 ant-design-vue
是因为咱们下面应用了局部加载的形式,如果应用 cdn
这种形式是加载全副的代码,有点节约。
没有应用 exclejs
,是因为exceljs
在我的业务代码中不是间接援用的,而是一个叫 table2excel
间接依赖的。所以就算我通过下面的办法排除掉它,在打包的时候还是会通过 table2excel
的依赖找到它并打包。
那这种不可避免的状况,该如何优化,让加载速度不受影响呢?
答案是通过 懒加载 的形式:
1.script 标签中正文掉 import Table2Excel from "table2excel.js";
2. 下载的办法中:download(){// 应用 import().then()形式
import("table2excel.js").then((Table2Excel) => {new Table2Excel.default("#table").export('filename') // 多了一层 default
})
}
这样在进入零碎时,不会加载Table2Excel
和exceljs
,当须要时才会去加载,第一次会慢一点,前面就不须要加载了,会变快。
3 moment.js 的优化
咱们发现 monentjs
在我的项目中有应用来对工夫格式化,然而应用频率并不高,齐全能够本人实现一个 format
办法,或者应用只有 6kb
的day.js
.
但这里咱们暂不替换,把 moment
变得瘦小一些即可,删除掉除中文以外的语言包。
第一步:vue.config.js
... 其它配置
chainWebpack: config => {config.plugin('ignore')
// 疏忽 /moment/locale 下的所有文件
.use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/))
}
... 其它配置
第二步:main.js
import moment from 'moment'
// 手动引入所须要的语言包
import 'moment/locale/zh-cn';
// 指定应用的语言
moment.locale('zh-cn');
这次咱们看看 moment
打包后多大:
只有 174kb
了。不过,有一说一还是 day.js
香~
做完下面这些动作咱们的 js 文件总大小:3.04MB
,其中蕴含 1.3MB
的懒加载 js,剩下的 1.7MB
左右的 js 基本上不会对页面造成很大的卡顿。
还有提高空间?
1. 通过 compression-webpack-plugin
插件把代码压缩为 gzip。然而!须要服务器反对
webpack
端 vue.config.js
配置如下:
// 打包压缩动态文件插件
const CompressionPlugin = require("compression-webpack-plugin")
//... 其它配置
module.exports = {
//... 其它配置
chainWebpack: config => {
// 生产环境开启 js\css 压缩
if (isProduction) {config.plugin('compressionPlugin').use(new CompressionPlugin({test: /\.(js)$/, // 匹配文件名
threshold: 10240, // 对超过 10k 的数据压缩
minRatio: 0.8,
deleteOriginalAssets: true // 删除源文件
}))
}
}
//... 其它配置
}
打包大小由 3MB
到860KB
,感觉腾飞了~
服务器端配置这里就不具体阐明了能够谷百:nginx 开启动态压缩 找到答案。
最初贴上优化前后的无缓存下的首屏加载工夫比照(chrome 浏览器),相对包真:
优化前我的项目网站首屏加载数据:9.17s
优化后我的项目网站首屏加载数据:1.24s
这些都是在工作之余,本人抽时间去查阅各位大佬的帖子,尽管都是些耍栏了的技术,然而真的要在本人我的项目中施行还是须要一些工夫和精力,大多数都是为了实现性能疾速迭代而疏忽掉了做程序本来的目标,就是要让用户有一个良好的应用体验。
肯请各位大佬, 不要忘了给我 点赞
、 评论
、 珍藏
。
往期精彩:
1. 什么是迭代器(iterator)?Generator 和它有什么关联
2. 微信小程序 UI 组件、图表、自定义 bar 这些坑都帮你踩了