webpack優(yōu)化坊秸,首屏渲染從9s到1s

1.生產(chǎn)環(huán)境關(guān)閉productionSourceMapcss 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的文件大虚献薄:

  1. element-ui和ant-design占了近1/4的大醒昧妗:1.53MB

  2. exceljs也是個(gè)大東西有:1.3MB

  3. echarts.js文件也接近1MB

  4. 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)了。
方案:

  1. 舍棄antd組件,自己去找一個(gè)類似的vue插件或者干脆自己實(shí)現(xiàn)一個(gè)虱肄。(這個(gè)方法短時(shí)間無(wú)法完成致板,且不想去動(dòng)以前代碼,暫不考慮)

  2. 使用antd部分加載咏窿。只加載想要的進(jìn)度條組件斟或,可以減少文件體積(這個(gè)方法簡(jiǎn)單粗暴,就是犧牲一些文件大屑丁)萝挤。

我們使用方案2,根據(jù)antd官方的文檔配置部分組件的引入根欧。

安裝 npm install babel-plugin-import -D

  1. main.js導(dǎo)入需要的組件 Step
import { Steps } from 'ant-design-vue'; 
Vue.component(Steps.name, Steps); 
Vue.component(Steps.Step.name, Steps.Step);
  1. 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ì)加載Table2Excelexceljs因悲,當(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方法,或者使用只有6kbday.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ù)器支持
webpackvue.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 // 刪除源文件
            }))
        }
    }
    //...其它配置
}

打包大小由3MB860KB蛤肌,感覺(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)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市恼蓬,隨后出現(xiàn)的幾起案子惊完,更是在濱河造成了極大的恐慌,老刑警劉巖处硬,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件小槐,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡荷辕,警方通過(guò)查閱死者的電腦和手機(jī)凿跳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)疮方,“玉大人控嗜,你說(shuō)我怎么就攤上這事÷庀裕” “怎么了疆栏?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)惫谤。 經(jīng)常有香客問(wèn)我壁顶,道長(zhǎng),這世上最難降的妖魔是什么溜歪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任若专,我火速辦了婚禮,結(jié)果婚禮上痹愚,老公的妹妹穿的比我還像新娘富岳。我一直安慰自己,他們只是感情好拯腮,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布窖式。 她就那樣靜靜地躺著,像睡著了一般动壤。 火紅的嫁衣襯著肌膚如雪萝喘。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天琼懊,我揣著相機(jī)與錄音阁簸,去河邊找鬼。 笑死哼丈,一個(gè)胖子當(dāng)著我的面吹牛启妹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播醉旦,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼饶米,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼桨啃!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起檬输,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤照瘾,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后丧慈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體析命,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年逃默,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鹃愤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡完域,死狀恐怖昼浦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情筒主,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布鸟蟹,位于F島的核電站乌妙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏建钥。R本人自食惡果不足惜藤韵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望熊经。 院中可真熱鬧泽艘,春花似錦、人聲如沸镐依。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)槐壳。三九已至然低,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間务唐,已是汗流浹背雳攘。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枫笛,地道東北人吨灭。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像刑巧,于是被迫代替她去往敵國(guó)和親喧兄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子无畔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容