記前端項(xiàng)目首屏加載優(yōu)化(網(wǎng)絡(luò)篇)

繼之前的一篇《記前端項(xiàng)目首屏加載優(yōu)化(打包篇)》之后,這次來(lái)講一講我的首屏加載在網(wǎng)絡(luò)方面的優(yōu)化??。

寫(xiě)在前面

資源加載是一個(gè)網(wǎng)站的展示在用戶瀏覽器的必經(jīng)之路,資源的請(qǐng)求次數(shù)和響應(yīng)時(shí)間決定了網(wǎng)站的加載體驗(yàn)。本篇主要針對(duì)請(qǐng)求次數(shù)和響應(yīng)時(shí)間聊一聊優(yōu)化過(guò)程。

網(wǎng)站分析與測(cè)試環(huán)境

有很多工具可以檢測(cè)網(wǎng)站的網(wǎng)絡(luò)請(qǐng)求:比如WebPage Speed TestInstant Website Test,這些工具可以分析網(wǎng)站的加載速度、安全性、可靠性等很多方面。而我是希望能夠在本地開(kāi)發(fā)過(guò)程中分析并優(yōu)化,所以我還是選擇Chrome Devtool 里的Network panel 進(jìn)行分析。

本地開(kāi)發(fā)環(huán)境的資源跟線上是有所不同的,本地的資源一般沒(méi)有壓縮,而線上有壓縮,這樣就會(huì)造成測(cè)試環(huán)境不真實(shí),所以需要在本地模擬線上的打包環(huán)境,編譯出跟線上環(huán)境一樣的包來(lái)加載,這樣分析出來(lái)的結(jié)果才有意義。

在上一篇《記前端項(xiàng)目首屏加載優(yōu)化(打包篇)》有寫(xiě)到過(guò)在本地打包一個(gè)和線上環(huán)境一致的壓縮配置,在package.json加入下面的配置:

"scripts": {
    ...
    "local_production": "cross-env NODE_ENV=local_production npm run build"
}

然后在webpack配置里面判斷process.env.NODE_ENV === 'local_production',便構(gòu)建出production環(huán)境的包即可。

gzip壓縮

打包出來(lái)的包大小1.7M,所有的依賴包index.xxx.js有748k這么大,所以需要開(kāi)啟gzip壓縮,可以大大減小加載大小,首先安裝express 的gzip包 compression:

npm install -D compression

然后添加express中間件:

var compression = require('compression');
app.use(compression());

打包后啟動(dòng)服務(wù)器,瀏覽器訪問(wèn),這時(shí)候index.xxx.js已經(jīng)壓縮到212kb??

image.png

開(kāi)啟http2.0

http1.x時(shí)代的優(yōu)化折磨好長(zhǎng)一段時(shí)間,各種奇淫技巧為了彌補(bǔ)http1的短板,影響著我們的開(kāi)發(fā)專注度,好在http2已經(jīng)開(kāi)始盛行,相信不久的將來(lái)可以完全替代http1。

現(xiàn)在基本主流的瀏覽器都支持http2.0了
http2-瀏覽器支持

http2.0大幅提升了加載性能,相比http1增加了多路復(fù)用、二進(jìn)制分幀、header壓縮等特性

開(kāi)啟http2也很簡(jiǎn)單,前提是開(kāi)啟了https協(xié)議,只要在Nginx配置文件中找到你要開(kāi)啟http2.0的域名server模塊,然后將 listen 443 ssl;改成 listen 443 ssl http2; 即可。

server {

    listen 443 ssl http2;
    server_name domain.com;

    ssl_certificate /path/to/public.crt;
    ssl_certificate_key /path/to/private.key;
    
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #允許的協(xié)議 
    ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; #加密算法(CloudFlare 推薦的加密套件組) 
    ssl_prefer_server_ciphers on; #優(yōu)化 SSL 加密套件 
    ssl_session_timeout 10m; #客戶端會(huì)話緩存時(shí)間 
    ssl_session_cache builtin:1000 shared:SSL:10m; #SSL 會(huì)話緩存類型和大小 
    ssl_buffer_size 1400; # 1400 bytes to fit in one MTU

檢查請(qǐng)求是否已經(jīng)開(kāi)啟http2,可以在chrome的network面板點(diǎn)鼠標(biāo)右鍵,選中protocol,就可以看到該請(qǐng)求是否開(kāi)啟了http2,圖中h2就代表http2:


http2

順便提一句,很多第三方的SDK都沒(méi)有開(kāi)啟http2??

CDN加速

項(xiàng)目開(kāi)發(fā)中用到的靜態(tài)資源和打包后的資源都可以傳到cdn以提高加載速度,我的項(xiàng)目是用七牛的上傳腳本,在npm run build之后執(zhí)行上傳腳本將dist目錄上傳到cdn上,注意在webpack配置里要配置publish_path對(duì)應(yīng)上傳cdn后的域名路徑。具體看七牛的上傳腳本文檔

構(gòu)建線上環(huán)境的publicPath的值可以是cdn的域名+路徑的形式,結(jié)尾要加/
"https://cdn.xxx.com/static/

webpack的output里配置publicPath

output: {
    path: DIST_PATH,
    publicPath: publicPath,
  },

webpack的圖片資源Loader應(yīng)添加相應(yīng)配置publicPath

    {
      test: /\.(jpg|gif|ico|png|svg|mp4|mp3)$/,
        use: `url-loader?limit=10&name=asset/[name]_[hash:5].[ext]&publicPath=${config.PUBLIC_PATH_ASSET}`,
        exclude: /(node_modules)/,
      },
      {
        test: /\.(woff|eot|ttf)\??.*$/i,
        loader: `url-loader?limit=1000&name=fonts/[name].[hash].[ext]&publicPath=${config.PUBLIC_PATH_ASSET}`,
        exclude: /(node_modules)/,
      },

無(wú)模塊化js的按需加載

有些時(shí)候我們引入的第三方插件是不能被webpack優(yōu)化按需加載,或者是沒(méi)有提供模塊化加載的(只能通過(guò)script標(biāo)簽引入的)插件,比如像tinymce富文本編輯器,由于它的加載方式是靠script標(biāo)簽引入tinymce.js,并靠tinymce.js里自身的加載機(jī)制去另外加載主題theme.js或者相關(guān)plugin.js。

這種第三方插件無(wú)法做成模塊化。這樣的話我們是不是就只能在入口index.html加script標(biāo)簽引入它,被迫在首屏加載這個(gè)暫時(shí)用不到的大文件???

我找到了webpack-require-http來(lái)幫忙??,他可以幫我用require語(yǔ)句幫我加載遠(yuǎn)程js,并提供了回調(diào)??,于是我便可以控制在什么時(shí)候加載tinymce??。

我的項(xiàng)目是按路由按需加載的,首頁(yè)沒(méi)有用到富文本編輯器所以沒(méi)必要加載,而論壇頁(yè)需要用到富文本編輯器,于是我們可以在react-router路由配置里的添加onEnter鉤子,在進(jìn)入論壇頁(yè)的時(shí)候才加載tinymce。

// 在需要tinymce編輯器的路由時(shí)提前加載
const require_tinymce = (nextState, replace, cb) => {
  require('https://cdn.bootcss.com/tinymce/4.7.13/jquery.tinymce.min.js').then(() => {
    cb();
  });
};

// router-config.js
{
    path: 'forum/:forum_id',
    component: forum_route,
    onEnter: require_tinymce,
},

這樣子如果訪問(wèn)首頁(yè)的話,首屏就少加載了這個(gè)big guy,經(jīng)測(cè)試,在模擬1M/s 的網(wǎng)速下訪問(wèn)網(wǎng)站,出現(xiàn)首屏界面的時(shí)間快了2s左右,2s! ??...,這可以說(shuō)是最大力度的一次優(yōu)化了。

緩存

緩存有很多種方式,大部分是服務(wù)器端處理的,而客戶端處理的則一般是把資源緩存在本地。

比較有效的本地緩存一般是用application-cache或者service worker將網(wǎng)站的資源緩存到本地,再次訪問(wèn)時(shí)直接調(diào)用本地的緩存資源,幾乎是本地打開(kāi)的速度,但是我的項(xiàng)目里的資源用到了CDN配置,所有的資源都在CDN外鏈中,而剛才提到的兩種緩存方式都不支持緩存跨域資源??。

這時(shí)候就得權(quán)衡一下了??,如果是首次訪問(wèn)網(wǎng)站的瀏覽器,加載時(shí)間cdn服務(wù)器會(huì)比自身服務(wù)器快一些,而二次加載則后者更快,只是網(wǎng)站緩存需要自己維護(hù)一套配置,如果配置不得當(dāng),會(huì)落下很嚴(yán)重的坑??,所以目前我還是先選擇相對(duì)保守的CDN加載,等以后慢慢磨合??。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容