1.生產(chǎn)環(huán)境關(guān)閉productionSourceMap
、css sourceMap
眾所周知选脊,SourceMap
就是當(dāng)頁(yè)面出現(xiàn)某些錯(cuò)誤,能夠定位到具體的某一行代碼脸甘,SourceMap
就是幫你建立這個(gè)映射關(guān)系的恳啥,方便代碼調(diào)試。在生產(chǎn)環(huán)境中我們完全沒(méi)必要開(kāi)啟這個(gè)功能(誰(shuí)在生產(chǎn)環(huán)境調(diào)試代碼丹诀?不會(huì)是你吧)
如下配置:
const isProduction = process.env.NODE_ENV === 'production'
// 判斷是否是生產(chǎn)環(huán)境
module.exports = {
productionSourceMap: !isProduction, //關(guān)閉生產(chǎn)環(huán)境下的SourceMap映射文件
css: {
sourceMap: !isProduction, // css sourceMap 配置
loaderOptions: {
...其它代碼
}
},
...其它代碼
}
此時(shí)再npm run build
打包钝的,就會(huì)發(fā)現(xiàn)速度快了很多,體積瞬間只有幾兆了铆遭!
2.分析大文件硝桩,找出內(nèi)鬼
安裝 npm install webpack-bundle-analyzer -D
插件,打包后會(huì)生產(chǎn)一個(gè)本地服務(wù)枚荣,清楚的展示打包文件的包含關(guān)系和大小碗脊。
vue.config.js
配置:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
...其它
configureWebpack: [
plugins: [
new BundleAnalyzerPlugin() // 分析打包大小使用默認(rèn)配置
]
},
...其它
}
自動(dòng)彈出一個(gè)服務(wù),清晰的展示打包后js的文件大虚献薄:
element-ui和ant-design占了近1/4的大醒昧妗:
1.53MB
。exceljs也是個(gè)大東西有:
1.3MB
echarts.js文件也接近
1MB
moment.js也有
700KB
打包后js文件一共就5MB害碾,這五個(gè)哥們就占了4M左右矢劲。不分析好還,一分析嚇得夠嗆~
不要虛慌随!找到刺了芬沉,一個(gè)一個(gè)來(lái)拔掉就好了。相信我拔掉的過(guò)程是很爽的阁猜。
一個(gè)一個(gè)解決丸逸,拔刺
把必須要用的第三方j(luò)s通過(guò)cdn的方式引用
分析發(fā)現(xiàn),elementui蹦漠、echarts
是必須使用的椭员,打包又耗時(shí)且頁(yè)面加載也較慢得很〉言埃可以通過(guò)cdn
直接引入隘击,方便且速度快。
element-ui
是我們項(xiàng)目用的主要框架研铆,所以這個(gè)肯定是少不了埋同,但是項(xiàng)目里面ant-design
為什么會(huì)存在呢,原來(lái)是發(fā)現(xiàn)有個(gè)頁(yè)面使用了antd
的進(jìn)度條組件棵红,因?yàn)?code>elementui的進(jìn)度條不太好看凶赁。但是沒(méi)想到這樣把整個(gè)antd
都導(dǎo)進(jìn)來(lái)了。
方案:
舍棄
antd
組件,自己去找一個(gè)類似的vue
插件或者干脆自己實(shí)現(xiàn)一個(gè)虱肄。(這個(gè)方法短時(shí)間無(wú)法完成致板,且不想去動(dòng)以前代碼,暫不考慮)使用
antd
部分加載咏窿。只加載想要的進(jìn)度條組件斟或,可以減少文件體積(這個(gè)方法簡(jiǎn)單粗暴,就是犧牲一些文件大屑丁)萝挤。
我們使用方案2,根據(jù)antd官方的文檔配置部分組件的引入根欧。
安裝 npm install babel-plugin-import -D
-
main.js
導(dǎo)入需要的組件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
}
]
]
}
此時(shí)再分析怜珍,antd
已經(jīng)小了很多。
2.使用cdn加載第三方j(luò)s凤粗。
我們項(xiàng)目里面第三方js
很多酥泛,有些打包下來(lái)會(huì)很大,而且加載速度較慢侈沪。我們把這些js分離出來(lái)揭璃,通過(guò)cdn
的方式在html
中的script
標(biāo)簽中直接使用,一方面減少打包體積亭罪,一方面提高了加載速度瘦馍。
這里推薦一個(gè)免費(fèi)的cdn
: BootCDN。也可以使用自己購(gòu)買(mǎi)的付費(fèi)cdn
服務(wù)应役,我們到網(wǎng)站搜索自己項(xiàng)目需要的js
情组。例如:vue
[圖片上傳失敗...(image-152539-1650424840084)]
注意,一定要選擇自己項(xiàng)目對(duì)應(yīng)的版本箩祥,否則會(huì)出現(xiàn)各種奇怪的問(wèn)題
我的項(xiàng)目使用的是 "vue": "^2.6.12",
(package.json)
[圖片上傳失敗...(image-df5b4-1650424840084)]
第一步:配置vue.config.js
院崇,讓webpack
不打包這些js,而是通過(guò)script
標(biāo)簽加入袍祖。
const isProduction = process.env.NODE_ENV === 'production' // 判斷是否是生產(chǎn)環(huán)境
//正式環(huán)境不打包公共js
let externals = {}
//儲(chǔ)存cdn的文件
let cdn = {
css: [
'https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.0/theme-chalk/index.min.css' // element-ui css 樣式表
],
js: []
}
//正式環(huán)境才需要
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變量 (打包時(shí)會(huì)執(zhí)行)
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>
可以發(fā)現(xiàn)cdn.js
中蕉陋,我把vue捐凭、echarts、element-ui
這三個(gè)大頭加入了凳鬓。在externals
對(duì)象中左側(cè)是npm
包的名稱茁肠,右側(cè)是在代碼中暴露的全局變量。注意element-ui
對(duì)應(yīng)的是 ELEMENT
缩举。
沒(méi)有ant-design-vue
是因?yàn)槲覀兩厦媸褂昧瞬糠旨虞d的方式垦梆,如果使用cdn
這種方式是加載全部的代碼匹颤,有點(diǎn)浪費(fèi)。
沒(méi)有使用exclejs
托猩,是因?yàn)?code>exceljs在我的業(yè)務(wù)代碼中不是直接引用的印蓖,而是一個(gè)叫table2excel
間接依賴的。所以就算我通過(guò)上面的方法排除掉它京腥,在打包的時(shí)候還是會(huì)通過(guò)table2excel
的依賴找到它并打包另伍。
那這種不可避免的情況,該如何優(yōu)化绞旅,讓加載速度不受影響呢?
答案是通過(guò)懶加載的方式:
1.script標(biāo)簽中注釋掉 import Table2Excel from "table2excel.js";
2.下載的方法中:download(){
1.script標(biāo)簽中注釋掉 import Table2Excel from "table2excel.js";
2.下載的方法中:
download(){
//使用import().then()方式
import("table2excel.js").then((Table2Excel) => {
new Table2Excel.default("#table").export('filename') //多了一層default
})
}
這樣在進(jìn)入系統(tǒng)時(shí)温艇,不會(huì)加載Table2Excel
和exceljs
因悲,當(dāng)需要時(shí)才會(huì)去加載,第一次會(huì)慢一點(diǎn)勺爱,后面就不需要加載了晃琳,會(huì)變快。
- 3 moment.js的優(yōu)化
我們發(fā)現(xiàn)monentjs
在項(xiàng)目中有使用來(lái)對(duì)時(shí)間格式化琐鲁,但是使用頻率并不高卫旱,完全可以自己實(shí)現(xiàn)一個(gè)format
方法,或者使用只有6kb
的day.js
.
但這里我們暫不替換围段,把moment
變得瘦小一些即可顾翼,刪除掉除中文以外的語(yǔ)言包。
第一步:**vue.config.js**
...其它配置
chainWebpack: config => {
config.plugin('ignore')
//忽略/moment/locale下的所有文件
.use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/))
}
...其它配置
第二步:main.js
import moment from 'moment' //手動(dòng)引入所需要的語(yǔ)言包
import 'moment/locale/zh-cn'; // 指定使用的語(yǔ)言
moment.locale('zh-cn');`
這次我們看看moment
打包后多大:
[圖片上傳失敗...(image-238672-1650424840084)]
只有174kb
了奈泪。不過(guò)适贸,有一說(shuō)一還是day.js
香~
做完上面這些動(dòng)作我們的js文件總大小:3.04MB
涝桅,其中包含 1.3MB
的懶加載js拜姿,剩下的1.7MB
左右的js基本上不會(huì)對(duì)頁(yè)面造成很大的卡頓。
[圖片上傳失敗...(image-a20f81-1650424840084)]
還有進(jìn)步空間冯遂?
1.通過(guò) compression-webpack-plugin
插件把代碼壓縮為gzip蕊肥。但是!需要服務(wù)器支持
webpack
端 vue.config.js
配置如下:
//打包壓縮靜態(tài)文件插件
const CompressionPlugin = require("compression-webpack-plugin")
//...其它配置
module.exports = {
//...其它配置
chainWebpack: config => {
//生產(chǎn)環(huán)境開(kāi)啟js\css壓縮
if (isProduction) {
config.plugin('compressionPlugin').use(new CompressionPlugin({
test: /\.(js)$/, // 匹配文件名
threshold: 10240, // 對(duì)超過(guò)10k的數(shù)據(jù)壓縮
minRatio: 0.8,
deleteOriginalAssets: true // 刪除源文件
}))
}
}
//...其它配置
}
打包大小由3MB
到860KB
蛤肌,感覺(jué)起飛了~
[圖片上傳失敗...(image-e79200-1650424840084)]
服務(wù)器端配置這里就不詳細(xì)說(shuō)明了可以谷百:nginx開(kāi)啟靜態(tài)壓縮 找到答案壁却。
最后貼上優(yōu)化前后的無(wú)緩存下的首屏加載時(shí)間對(duì)比(chrome瀏覽器),絕對(duì)包真:
優(yōu)化前項(xiàng)目網(wǎng)站首屏加載數(shù)據(jù):9.17s
[圖片上傳失敗...(image-7b5f48-1650424840084)]
優(yōu)化后項(xiàng)目網(wǎng)站首屏加載數(shù)據(jù):1.24s
[圖片上傳失敗...(image-4b0505-1650424840084)]
這些都是在工作之余寻定,自己抽時(shí)間去查閱各位大佬的帖子儒洛,雖然都是些耍爛了的技術(shù),但是真的要在自己項(xiàng)目中實(shí)施還是需要一些時(shí)間和精力狼速,大多數(shù)都是為了完成功能快速迭代而忽略掉了做程序原本的目的琅锻,就是要讓用戶有一個(gè)良好的使用體驗(yàn)。