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左右。不分析好還,一分析嚇得夠嗆~
不要虛!找到刺了,一個一個來拔掉就好了。相信我拔掉的過程是很爽的。
一個一個解決,拔刺
把必須要用的第三方js通過cdn的方式引用
分析發現,elementui、echarts
是必須使用的,打包又耗時且頁面加載也較慢得很。可以通過cdn
直接引入,方便且速度快。
element-ui
是我們項目用的主要框架,所以這個肯定是少不了,但是項目里面ant-design
為什么會存在呢,原來是發現有個頁面使用了antd
的進度條組件,因為elementui
的進度條不太好看。但是沒想到這樣把整個antd
都導進來了。
方案:
舍棄
antd
組件,自己去找一個類似的vue
插件或者干脆自己實現一個。(這個方法短時間無法完成,且不想去動以前代碼,暫不考慮)使用
antd
部分加載。只加載想要的進度條組件,可以減少文件體積(這個方法簡單粗暴,就是犧牲一些文件大小)。
我們使用方案2,根據antd官方的文檔配置部分組件的引入。
安裝 npm install babel-plugin-import -D
-
main.js
導入需要的組件Step
import { Steps } from 'ant-design-vue';
Vue.component(Steps.name, Steps);
Vue.component(Steps.Step.name, Steps.Step);
-
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
[圖片上傳失敗...(image-152539-1650424840084)]
注意,一定要選擇自己項目對應的版本,否則會出現各種奇怪的問題
我的項目使用的是 "vue": "^2.6.12",
(package.json)
[圖片上傳失敗...(image-df5b4-1650424840084)]
第一步:配置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">
<section id="app"></section>
</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(){
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
打包后多大:
[圖片上傳失敗...(image-238672-1650424840084)]
只有174kb
了。不過,有一說一還是day.js
香~
做完上面這些動作我們的js文件總大小:3.04MB
,其中包含 1.3MB
的懶加載js,剩下的1.7MB
左右的js基本上不會對頁面造成很大的卡頓。
[圖片上傳失敗...(image-a20f81-1650424840084)]
還有進步空間?
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
,感覺起飛了~
[圖片上傳失敗...(image-e79200-1650424840084)]
服務器端配置這里就不詳細說明了可以谷百:nginx開啟靜態壓縮 找到答案。
最后貼上優化前后的無緩存下的首屏加載時間對比(chrome瀏覽器),絕對包真:
優化前項目網站首屏加載數據:9.17s
[圖片上傳失敗...(image-7b5f48-1650424840084)]
優化后項目網站首屏加載數據:1.24s
[圖片上傳失敗...(image-4b0505-1650424840084)]
這些都是在工作之余,自己抽時間去查閱各位大佬的帖子,雖然都是些耍爛了的技術,但是真的要在自己項目中實施還是需要一些時間和精力,大多數都是為了完成功能快速迭代而忽略掉了做程序原本的目的,就是要讓用戶有一個良好的使用體驗。