繼以前的一篇《記前端項目首屏加載優化(打包篇)》以後,此次來說一講個人首屏加載在網絡方面的優化😏。javascript
資源加載是一個網站的展現在用戶瀏覽器的必經之路,資源的請求次數和響應時間決定了網站的加載體驗。本篇主要針對請求次數和響應時間聊一聊優化過程。css
有不少工具能夠檢測網站的網絡請求:好比WebPage Speed Test,Instant Website Test,這些工具能夠分析網站的加載速度、安全性、可靠性等不少方面。而我是但願可以在本地開發過程當中分析並優化,因此我仍是選擇Chrome Devtool 裏的Network panel 進行分析。html
本地開發環境的資源跟線上是有所不一樣的,本地的資源通常沒有壓縮,而線上有壓縮,這樣就會形成測試環境不真實,因此須要在本地模擬線上的打包環境,編譯出跟線上環境同樣的包來加載,這樣分析出來的結果纔有意義。前端
在上一篇《記前端項目首屏加載優化(打包篇)》有寫到過在本地打包一個和線上環境一致的壓縮配置,在package.json加入下面的配置:java
"scripts": { ... "local_production": "cross-env NODE_ENV=local_production npm run build" }
而後在webpack配置裏面判斷process.env.NODE_ENV === 'local_production',便構建出production環境的包便可。node
打包出來的包大小1.7M,全部的依賴包index.xxx.js有748k這麼大,因此須要開啓gzip壓縮,能夠大大減少加載大小,首先安裝express 的gzip包 compression
:react
npm install -D compression
而後添加express中間件:jquery
var compression = require('compression'); app.use(compression());
打包後啓動服務器,瀏覽器訪問,這時候index.xxx.js已經壓縮到212kb😎webpack
http1.x時代的優化折磨好長一段時間,各類奇淫技巧爲了彌補http1的短板,影響着咱們的開發專一度,好在http2已經開始盛行,相信不久的未來能夠徹底替代http1。web
如今基本主流的瀏覽器都支持http2.0了
http2.0大幅提高了加載性能,相比http1增長了多路複用、二進制分幀、header壓縮等特性
開啓http2也很簡單,前提是開啓了https協議,只要在Nginx配置文件中找到你要開啓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; #容許的協議 ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5; #加密算法(CloudFlare 推薦的加密套件組) ssl_prefer_server_ciphers on; #優化 SSL 加密套件 ssl_session_timeout 10m; #客戶端會話緩存時間 ssl_session_cache builtin:1000 shared:SSL:10m; #SSL 會話緩存類型和大小 ssl_buffer_size 1400; # 1400 bytes to fit in one MTU
檢查請求是否已經開啓http2,能夠在chrome的network面板點鼠標右鍵,選中protocol,就能夠看到該請求是否開啓了http2,圖中h2就表明http2:
順便提一句,不少第三方的SDK都沒有開啓http2🤔
項目開發中用到的靜態資源和打包後的資源均可以傳到cdn以提升加載速度,個人項目是用七牛的上傳腳本,在npm run build
以後執行上傳腳本將dist
目錄上傳到cdn上,注意在webpack配置裏要配置publish_path
對應上傳cdn後的域名路徑。具體看七牛的上傳腳本文檔
構建線上環境的publicPath的值能夠是cdn的域名+路徑的形式,結尾要加/
:
"https://cdn.xxx.com/static/
webpack的output
裏配置publicPath
:
output: { path: DIST_PATH, publicPath: publicPath, },
webpack的圖片資源Loader應添加相應配置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)/, },
有些時候咱們引入的第三方插件是不能被webpack優化按需加載,或者是沒有提供模塊化加載的(只能經過script標籤引入的)插件,好比像tinymce富文本編輯器,因爲它的加載方式是靠script標籤引入tinymce.js,並靠tinymce.js裏自身的加載機制去另外加載主題theme.js或者相關plugin.js。
這種第三方插件沒法作成模塊化。這樣的話咱們是否是就只能在入口index.html加script標籤引入它,被迫在首屏加載這個暫時用不到的大文件🤔?
我找到了webpack-require-http來幫忙😎,他能夠幫我用require
語句幫我加載遠程js,並提供了回調🤝,因而我即可以控制在何時加載tinymce🤘。
個人項目是按路由按需加載的,首頁沒有用到富文本編輯器因此不必加載,而論壇頁須要用到富文本編輯器,因而咱們能夠在react-router
路由配置裏的添加onEnter鉤子,在進入論壇頁的時候才加載tinymce。
// 在須要tinymce編輯器的路由時提早加載 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, },
這樣子若是訪問首頁的話,首屏就少加載了這個big guy,經測試,在模擬1M/s 的網速下訪問網站,出現首屏界面的時間快了2s左右,2s! 😱...,這能夠說是最大力度的一次優化了。
緩存有不少種方式,大部分是服務器端處理的,而客戶端處理的則通常是把資源緩存在本地。
比較有效的本地緩存通常是用application-cache
或者service worker
將網站的資源緩存到本地,再次訪問時直接調用本地的緩存資源,幾乎是本地打開的速度,可是個人項目裏的資源用到了CDN配置,全部的資源都在CDN外鏈中,而剛纔提到的兩種緩存方式都不支持緩存跨域資源😞。
這時候就得權衡一下了🤔,若是是首次訪問網站的瀏覽器,加載時間cdn服務器會比自身服務器快一些,而二次加載則後者更快,只是網站緩存須要本身維護一套配置,若是配置不得當,會落下很嚴重的坑😂,因此目前我仍是先選擇相對保守的CDN加載,等之後慢慢磨合🙂。