前端項目優化 -Web 開發經常使用優化方案、Vue & React 項目優化

github

github-myBlob
css

從輸入URL到頁面加載完成的整個過程


  1. 首先作 DNS 查詢,若是這一步作了智能 DNS 解析的話,會提供訪問速度最快的 IP 地址回來
  2. 接下來是 TCP 握手,應用層會下發數據給傳輸層,這裏 TCP 協議會指明兩端的端口號,而後下發給網絡層。網絡層中的 IP 協議會肯定 IP 地址,而且指示了數據傳輸中如何跳轉路由器。而後包會再被封裝到數據鏈路層的數據幀結構中,最後就是物理層面的傳輸了
  3. TCP 握手結束後會進行 TLS 握手,而後就開始正式的傳輸數據(若是使用HTTPS)
  4. 數據在進入服務端以前,可能還會先通過負責負載均衡的服務器,它的做用就是將請求合理的分發到多臺服務器上,這時假設服務端會響應一個 HTML 文件
  5. 首先瀏覽器會判斷狀態碼是什麼,若是是 200 那就繼續解析,若是 400 或 500 的話就會報錯,若是 300 的話會進行重定向,這裏會有個重定向計數器,避免過屢次的重定向,超過次數也會報錯
  6. 瀏覽器開始解析文件,若是是 gzip 格式的話會先解壓一下,而後經過文件的編碼格式知道該如何去解碼文件
  7. 文件解碼成功後會正式開始渲染流程,先會根據 HTML 構建 DOM 樹,有 CSS 的話會去構建 CSSOM 樹。若是遇到script標籤的話,會判斷是否存在async或者defer,前者會並行進行下載並執行 JS,後者會先下載文件,而後等待 HTML 解析完成後順序執行,若是以上都沒有,就會阻塞住渲染流程直到 JS 執行完畢。遇到文件下載的會去下載文件,這裏若是使用 HTTP 2.0 協議的話會極大的提升多圖的下載效率。
  8. 初始的 HTML 被徹底加載和解析後會觸發DOMContentLoaded事件
  9. CSSOM 樹和 DOM 樹構建完成後會開始生成 Render 樹,這一步就是肯定頁面元素的佈局、樣式等等諸多方面的東西
  10. 在生成 Render 樹的過程當中,瀏覽器就開始調用 GPU 繪製,合成圖層,將內容顯示在屏幕上了
  11. 沒有要傳輸的文件了,斷開TCP鏈接 4 次揮手

性能優化分析


根據上面的過程能夠看到,頁面的加載過程主要分爲下載、解析、渲染三個步驟,總體能夠從兩個角度來考慮:html

  • 網頁的資源請求與加載階段
  • 網頁渲染階段

網頁的資源請求與加載階段

咱們能夠打開 Chrome 的調試工具來分析此階段的性能指標
在這裏插入圖片描述
在創建 TCP 鏈接的階段(HTTP 協議是創建在 TCP 協議之上的)前端

  • Queuing 和 Stalled 表示請求隊列以及請求等待的時間
  • DNS Lookup 表示執行 DNS 查詢所用的時間。頁面上的每個新域都須要完整的往返才能執行DNS查詢
  • Initila connection 和 SSL 包括 TCP 握手重試和協商 SSL 以及 SSL 握手的時間。

在請求響應的階段vue

  • Request sent 是發出網絡請求所用的時間,一般不會超過 1ms
  • Watiting(TTFB) 是等待初始響應所用的時間,也稱爲等待返回首個字節的時間,該時間將捕捉到服務器往返的延遲時間,以及等待服務器傳送響應所用的時間。
  • Content Download 則是從服務器上接收數據的時間。

資源請求階段優化方案

依據上面的指標給出如下幾點優化方案(僅供參考)react

一、劃分子域

條件:擁有多個域名
Chrome 瀏覽器只容許每一個源擁有 6 個 TCP 鏈接,所以能夠經過劃分子域的方式,將多個資源分佈在不一樣子域上用來減小請求隊列的等待時間。然而,劃分子域並非一勞永逸的方式,多個子域意味着更多的 DNS 查詢時間。一般劃分爲 3 到 5 個比較合適。
對如何拆分資源有以下建議:webpack

  • 前端類:把項目業務自己的 html、css、js、圖標等歸爲一類
  • 靜態類:CDN 資源
  • 動態類:後端 API

二、DNS 預解析

DNS 解析也是須要時間的,能夠經過預解析的方式來預先得到域名所對應的 IP,方法是在 head 標籤裏寫上幾個 link 標籤ios

<link rel="dns-prefetch" href="https://www.google.com">
<link rel="dns-prefetch" href="https://www.google-analytics.com">

對以上幾個網站提早解析,這個過程是並行的,不會阻塞頁面渲染。git

三、預加載

在開發中,可能會遇到這樣的狀況。有些資源不須要立刻用到,可是但願儘早獲取,這時候就可使用預加載。
預加載實際上是聲明式的 fetch,強制瀏覽器請求資源,而且不會阻塞 onload 事件,可使用如下代碼開啓預加載:github

<link rel="preload" href="http://example.com">

預加載能夠必定程度上下降首屏的加載時間,由於能夠將一些不影響首屏但重要的文件延後加載,惟一缺點就是兼容性很差。web

四、保持持久鏈接

HTTP 是一個無狀態的面向鏈接的協議,即每一個 HTTP 請求都是獨立的。然而無狀態並不表明 HTTP 不能保持 TCP 鏈接,Keep-Alive 正是 HTTP 協議中保持 TCP 鏈接很是重要的一個屬性。 HTTP1.1 協議中,Keep-Alive 默認打開,使得通訊雙方在完成一次通訊後仍然保持必定時長的鏈接,所以瀏覽器能夠在一個單獨的鏈接上進行多個請求,有效地下降創建 TCP 請求所消耗的時間。

五、CND 加速

使用 CND 加速能夠減小客戶端到服務器的網絡距離。

  • CDN 的意圖就是儘量地減小資源在轉發、傳輸、鏈路抖動等狀況下順利保障信息的連貫性;
  • CDN 系統可以實時地根據網絡流量和各節點的鏈接、負載情況以及到用戶的距離和響應時間等綜合信息將用戶的請求從新導向離用戶最近的服務節點上
  • CDN 採用各節點緩存的機制,當咱們項目的靜態資源修改後,若是 CDN 緩存沒有作相應更新,則看到的仍是舊的網頁,解決的辦法是刷新緩存,七牛雲、騰訊雲均可單獨針對某個文件/目錄進行刷新;
  • CDN 緩存須要合理地使用:圖片、經常使用 js 組件、css 重置樣式等,即不常改動的文件可走 CDN,包括項目內的一些介紹頁;

還有一種比較流行的作法是讓一些項目依賴走 CDN,好比 vuex、vue-router 這些插件經過外鏈的形式來引入,由於它們都有本身免費的 CDN,這樣能夠減小打包後的文件體積。

六、設置緩存

緩存對於前端性能優化來講是個很重要的點,良好的緩存策略能夠下降資源的重複加載提升網頁的總體加載速度。
一般瀏覽器緩存策略分爲兩種:強緩存協商緩存

  • 強緩存:實現強緩存能夠經過兩種響應頭實現:ExpiresCache-Control強緩存表示在緩存期間不須要向服務器發送請求
  • 協商緩存:緩存過時了就是用協商緩存,其經過Last-Modified/If-Modified-SinceETag/If-None-Match實現

HTTP 頭中與緩存相關的屬性,主要有如下幾個:

(1) Expires: 指定緩存過時的時間,是一個絕對時間,但受客戶端和服務端時鐘和時區差別的影響,是 HTTP/1.0 的產物
形如Expires: Wed, 22 Oct 2018 08:41:00 GMT

(2) Cache-Control:比 Expires 策略更詳細,max-age 優先級比 Expires 高,其值能夠是如下五種狀況

  1. no-cache: 強制全部緩存了該響應的緩存用戶,在使用已存儲的緩存數據前,發送請求到原始服務器(進行過時認證),一般狀況下,過時認證須要配合 etag 和 Last-Modified 進行一個比較
  2. no-store: 告訴客戶端不要響應緩存(禁止使用緩存,每一次都從新請求數據)
  3. public: 緩存響應,並能夠在多用戶間共享(與中間代理服務器相關)
  4. private: 緩存響應,但不能在多用戶間共享(與中間代理服務器相關)
  5. max-age: 緩存在指定時間(單位爲秒)後過時

(3) Last-Modified / If-Modified-Since: Last-Modified表示本地文件最後修改日期,If-Modified-Since會將上次從服務器獲取的Last-Modified的值發送給服務器,詢問服務器在該日期後資源是否有更新,有更新的話就會將新的資源發送回來。
可是若是(服務器)在本地打開緩存文件(或者刪了個字符 a 後又填上去),就會形成Last-Modified被修改,因此在 HTTP / 1.1 出現了ETag

(4) Etag / If-None-Match: ETag相似於文件指紋,If-None-Match會將當前ETag發送給服務器,詢問該資源ETag是否變更,有變更的話就將新的資源發送回來。而且ETag優先級比Last-Modified高。
因爲 etag 要使用少數的字符表示一個不定大小的文件(如 etag: "58c4e2a1-f7"),因此 etag 是有重合的風險的,若是網站的信息特別重要,連很小的機率如百萬分之一都不容許,那麼就不要使用 etag 了。使用 etag 的代價是增長了服務器的計算負擔,特別是當文件比較大時。

在這裏插入圖片描述

選擇合適的緩存策略
對於大部分的場景均可以使用強緩存配合協商緩存解決,可是在一些特殊的地方可能須要選擇特殊的緩存策略

  • 對於某些不須要緩存的資源,可使用Cache-control: no-store,表示該資源不須要緩存
  • 對於頻繁變更的資源,可使用Cache-Control: no-cache並配合ETag使用,表示該資源已被緩存,可是每次都會發送請求詢問資源是否更新。
  • 對於代碼文件來講,一般使用Cache-Control: max-age=31536000並配合策略緩存使用,而後對文件進行指紋處理,一旦文件名變更就會馬上下載新的文件。

七、使用 HTTP / 2.0

由於瀏覽器會有併發請求限制,在 HTTP / 1.1 時代,每一個請求都須要創建和斷開,消耗了好幾個 RTT 時間,而且因爲 TCP 慢啓動的緣由,加載體積大的文件會須要更多的時間。
在 HTTP / 2.0 中引入了多路複用,可以讓多個請求使用同一個 TCP 連接,極大的加快了網頁的加載速度。而且還支持 Header 壓縮,進一步的減小了請求的數據大小。

八、圖片和文件壓縮

這又涉及到不少知識點了,簡單來講,咱們要儘量地在保證咱們的 App 能正常運行、圖片儘量保證高質量的前提下去壓縮全部用到的文件的體積。好比圖片格式的選擇、去掉咱們代碼中的註釋、空行、無關代碼等。
圖片相關優化

  • 不用圖片。不少時候會使用到不少修飾類圖片,其實這類修飾圖片徹底能夠用 CSS 去代替。
  • 對於移動端來講,屏幕寬度就那麼點,徹底沒有必要去加載原圖浪費帶寬。通常圖片都用 CDN 加載,能夠計算出適配屏幕的寬度,而後去請求相應裁剪好的圖片。
  • 小圖使用 base64 格式
  • 選擇正確的圖片格式:
    • 對於可以顯示 WebP 格式的瀏覽器儘可能使用 WebP 格式。由於 WebP 格式具備更好的圖像數據壓縮算法,能帶來更小的圖片體積,並且擁有肉眼識別無差別的圖像質量,缺點就是兼容性並很差
    • 小圖使用 PNG,其實對於大部分圖標這類圖片,徹底可使用 SVG 代替
    • 照片使用 JPEG

構建工具的使用

  • 對於 Webpack4,打包項目使用 production 模式,這樣會自動開啓代碼壓縮
  • 使用 ES6 模塊來開啓 tree shaking,這個技術能夠移除沒有使用的代碼
  • 優化圖片,對於小圖可使用 base64 的方式寫入文件中
  • 按照路由拆分代碼,實現按需加載
  • 給打包出來的文件名添加哈希,實現瀏覽器緩存文件(能及時更新)
  • 啓用 gzip 壓縮(須要先後端支持)
  • 各類 loader/plugin 的使用

壓縮 HTML 文件
能夠把 HTML 的註釋去掉,把行前縮進刪掉,這樣處理的文件能夠明顯減小 HTML 的體積;這樣作幾乎是沒有風險的,除了 pre 標籤不可以去掉行首縮進以外,其餘的都正常。

網頁渲染階段優化方案

一、<script>標籤位置

渲染線程和 JS 引擎線程是互斥的,若是你想首屏渲染的越快,就越不該該在首屏就加載 JS 文件,所以建議將 script 標籤放在 body 標籤底部的緣由。或者使用給 script 標籤添加 defer 或者 async 屬性 。

  • defer 表示該文件會並行下載,可是會放到 HTML 解析完成後再順序執行;
  • 對於沒有任何依賴的 JS 文件能夠加上 async 屬性,表示加載和渲染後續文檔元素的過程將和 JS 文件的加載與執行並行無序進行

二、Webworker 的使用

執行 JS 代碼過長會卡住渲染,對於須要不少時間計算的代碼能夠考慮使用 Webworker。Webworker 可讓咱們另開一個線程執行腳本(這並無改變 JS 單線程的本質,由於新開的線程受控於主線程且不得操做 DOM)而不影響渲染。

三、懶加載

懶加載就是將不關鍵的資源延後加載。
懶加載的原理就是隻加載自定義區域(一般是可視區域,但也能夠是即將進入可視區域)內須要加載的東西。對於圖片來講,先設置圖片標籤的src屬性爲一張佔位圖,將真實的圖片資源放入一個自定義屬性中,當進入自定義區域時,就將自定義屬性替換爲src屬性,這樣圖片就會去下載資源,實現了圖片懶加載。
懶加載不只能夠用於圖片,也可使用在別的資源上。好比進入可視區域纔開始播放視頻等等。

四、預加載

  • 圖片等靜態資源在使用以前的提早請求
  • 資源使用到時能從緩存中加載,提高用戶體驗
  • 頁面展現的依賴關係維護

使用場景好比抽獎動畫展現過程當中預先加載其餘內容,或者電子書閱讀章節的預加載可使切換下一章節時更爲流暢。

五、減小回流與重繪

執行 JavaScript 的解析和 UI 渲染的兩個瀏覽器線程是互斥的,UI 渲染時 JS 代碼解析終止,反之亦然。
頁面佈局和幾何屬性 改變時,就會觸發 迴流
須要更新的只是元素的某些外觀 時,就會觸發 重繪

  • 用 translate 替代 top 屬性:top 會觸發 reflow,但 translate 不會
  • 不要一條一條地修改 DOM 的樣式,預先定義好 class,而後修改 DOM 的 className
  • 把 DOM 離線後修改,好比:先把 DOM 給 display:none(有一次 reflow),而後你修改 100 次,而後再把它顯示出來
  • 不要把 DOM 節點的屬性值放在一個循環裏當成循環的變量
  • offsetHeight、offsetWidth 每次都要刷新緩衝區,緩衝機制被破壞,先用變量存儲下來
  • 不要使用 table 佈局,可能很小的一個小改動會形成整個 table 的從新佈局
  • 動畫實現的速度的選擇:選擇合適的動畫速度
  • 啓用 gpu 硬件加速(並行運算),gpu 加速意味着數據須要從 cpu 走總線到 gpu 傳輸,須要考慮傳輸損耗.
    • transform:translateZ(0)
    • transform:translate3D(0)
    • 彷佛如今瀏覽器能智能地分析 gpu 加速了?

六、編寫高效率的 CSS

使用 CSS 預處理器時注意不要有過多的嵌套,嵌套層次過深會影響瀏覽器查找選擇器的速度,且必定程度上會產生出不少冗餘的字節。

七、減小 DOM 元素數量、減小 DOM 的操做

減小 DOM 元素數量,合理利用 :after、:before 等僞類,避免頁面過深的層級嵌套;
優化 JavaScript 性能,減小 DOM 操做次數(或集中操做),能有效規避頁面重繪/重排;
只能說盡量去作優化,如數據分頁、首屏直出、按需加載等

八、函數節流

爲觸發頻率較高的函數使用函數節流

其餘

SPA SEO SSR

SPA:單頁面富應用
動態地重寫頁面的部分與用戶交互而不是加載新的頁面。
優勢:① 先後端分離 ② 頁面之間切換快 ③ 後端只需提供 API
缺點:① 首屏速度慢,由於用戶首次加載 SPA 框架及應用程序的代碼而後才渲染頁面 ② 不利於 SEO
SEO(Search Engine Optimization):搜索引擎優化
經常使用技術:利用 <title> 標籤和 <meta> 標籤的 description

<html>
<head>
<title>標題內容</title>
  <meta name="description" content="描述內容">
  <meta name="keyword" content="關鍵字1,關鍵字2,—">
  </head>
</html>

SPA 應用中,一般經過 AJAX 獲取數據,而這裏就難以保證咱們的頁面能被搜索引擎正常收錄到。而且有一些搜索引擎不支持執行 JS 和經過 AJAX 獲取數據,那就更不用提 SEO 了。
對於有些網站而言,SEO 顯得相當重要,例如主要之內容輸出爲主的 Quora、stackoverflow、知乎和豆瓣等等,那如何才能正常使用 SPA 而又不影響 SEO 呢 ?因此有了 SSR
SSR(Server-Side Rendering):服務端渲染

如下內容部分參考《深刻淺出 React 與 Redux》- 程墨

爲了量化網頁性能,咱們定義兩個指標:

  • TTFP(Time To First Paint):指的是從網頁 HTTP 請求發出,到用戶能夠看到第一個有意義的內容渲染出來的時間差
  • TTI(Time To Interactive):指的是從網頁 HTTP 請求發出,到用戶能夠對網頁內容進行交互的時間

在一個 徹底靠瀏覽器端渲染 的應用中,當用戶在瀏覽器中打開一個頁面的時候,最壞狀況下沒有任何緩存,須要等待三個 HTTP 請求才能到達 TTFP 的時間點:

  • 向服務器獲取 HTML,這個 HTML 只是一個無內容的空架子,可是皮之不存毛將焉附,這個 HTML 就是皮,在其中運行的 JavaScript 就是毛,因此這個請求時不可省略的
  • 獲取 JavaScript 文件,大部分狀況下,若是這是瀏覽器第二次訪問這個網站,就能夠直接讀取緩存,不會發出真正的 HTTP 請求
  • 訪問 API 服務器獲取數據,獲得的數據將由 JavaScript 加工以後用來填充 DOM 樹,若是應用的是 React,那就是經過修改組件的狀態或者屬性來驅動渲染

而對於服務器端渲染,由於獲取 HTTP 請求以後就會返回全部有內容的 HTML,因此在一個 HTTP 的週期以後就會提供給瀏覽器有意義的內容,因此首次渲染時間 TTFP 會優於徹底依賴於瀏覽器端渲染的頁面。

除了更短的 TTFP,服務器端渲染還有一個好處就是利於搜索引擎優化,雖然某些搜索引擎已經可以索引瀏覽器端渲染的網頁,可是畢竟不是全部搜索引擎都能作到這一點,讓搜索引擎可以索引到應用頁面的最直接方法就是提供完整 HTML

上面的性能對比只是理論上的分析,實際上,採用服務器端渲染是否能得到更好的 TTFP 有多方面因素。
一、服務器端產生的 HTML 過大是否會影響性能?
由於服務器端渲染返回的是完整的 HTML,那麼下載這個 HTML 的時間也會增加。
二、服務器端渲染的運算消耗是不是服務器可以承擔得起的?
瀏覽器端渲染的方案下,服務器只提供靜態資源,壓力被分攤到了訪問用戶的瀏覽器中;若是使用服務器端渲染,每一個頁面請求都要產生 HTML 頁面,這樣服務器的壓力就會很大。

React 並非給服務器端渲染設計的,若是應用對 TTFP 要求不高,也不但願對 React 頁面進行搜索引擎優化,那麼沒有必要使用「同構」來增長開發難度;若是但願應用的性能能更進一步,並且服務器運算資源充足,那麼能夠嘗試。對 Vue 而言應該也是一樣的道理。


最後咱們來總結下服務端渲染理論上的優缺點:
優勢:

  • 更快的響應時間、首屏加載時間,能夠將 SEO 的關鍵信息直接在後臺渲染成 HTML,從而保證搜索引擎的爬蟲都能爬到關鍵數據
  • 更快的內容到達時間,特別是對於緩慢的網絡狀況或運行緩慢的設備
  • 無需等待全部的 JavaScript 都完成下載並執行,才顯示服務器渲染的標記,因此用戶將會更快速地看到完整渲染的頁面,一般能夠產生更好的用戶體驗
  • 資源文件從本地請求(各類 bundle 什麼的),更快的下載速度

缺點:

  • 佔用服務器更多的 CPU 和內存資源
  • 一些經常使用的瀏覽器 API 可能沒法使用,如 window、document、alert 等,若是須要使用的話須要對運行的環境加以判斷
  • 開發難度加大

Vue 項目優化點

一、第三方庫走 cdn
例如:

<script src="//cdn.bootcss.com/vue/2.2.5/vue.min.js"></script>
<script src="//cdn.bootcss.com/vue-router/2.3.0/vue-router.min.js"></script>
<script src="//cdn.bootcss.com/vuex/2.2.1/vuex.min.js"></script>
<script src="//cdn.bootcss.com/axios/0.15.3/axios.min.js"></script>

在 webpack 裏有個 externals 選項,能夠忽略不須要打包的庫
https://webpack.js.org/configuration/externals/#root

const path = require('path')

module.exports = {
  mode: 'production',
  entry: './src/index.js',
  externals: {
    'vue': 'Vue',
    'vue-router': 'VueRouter',
    'vuex': 'Vuex',
    'axios': 'axios'
  },
  output: {
    ...
  }
}

二、路由懶加載

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/ebook',
      component: () => import('./views/ebook/index.vue'), // 路由懶加載,這裏用的是ES6的語法  import()函數是動態加載 import 是靜態加載
      children: [ // 動態路由, 能夠傳遞路徑參數
        {
          path: ':fileName',
          component: () => import('./components/ebook/EbookReader.vue')
        }
      ]
    },
    {
      path: '/store',
      component: () => import('./views/store/index.vue'),
      redirect: '/store/shelf', // #/store -> #/store/home
      ...
    }
  ]
})

三、使用懶加載插件 Vue-Loader
具體的使用能夠參考 這篇文章 或者去看官方文檔
step1:cnpm install vue-lazyload --save
step2:main.js導入

import VueLazyLoad from 'vue-lazyload'
Vue.use(VueLazyload)

step3:<img class="item-pic" v-lazy="newItem.picUrl"/>vue 文件中將須要懶加載的圖片綁定v-bind:src修改成v-lazy
這只是圖片懶加載,還有不少其餘可選配置

四、v-ifv-show的選擇
通常來講,v-if有更高的切換開銷,而v-show有更高的初始渲染開銷。所以,若是須要很是頻繁地切換,則使用v-show較好;若是在運行時條件不多改變,則使用v-if較好。

React 項目優化點

一、單個組件的優化:更改 shouldComponentUpdate 函數的默認實現,根據每一個 React 組件的內在邏輯定製其行爲,減小沒必要要的從新渲染

shouldComponentUpdate(nextProps, nextState) {
  // 假設影響渲染內容的 prop 只有 completed 和 text,只須要確保
  // 這兩個 prop 沒有變化,函數就能夠返回 false
  return (nextProps.completed !== this.props.completed) ||
    (nextProps.text !== this.props.text)
}

二、使用 immutable.js 解決複雜數據 diff、clone 等問題。
immutable.js 實現原理:持久化數據結構,也就是使用舊數據建立新數據時,要保證舊數據同時可用且不變。同時爲了不 deepCopy 把全部節點都複製一遍帶來的性能損耗,Immutable 使用告終構共享,即若是對象樹中一個節點發生變化,只修改這個節點和受它影響的父節點,其它節點則進行共享。

三、在 constructor() 裏作 this 綁定
當在 render() 裏使用事件處理方法時,提早在構造函數裏把 this 綁定上去(若是須要的話),由於在每次 render 過程當中, 再調用 bind 都會新建一個新的函數,浪費資源.

// bad
class App extends React.Component {
  onClickDiv() {
    // do stuff
  }

  render() {
    return <div onClick={this.onClickDiv.bind(this)} />;
  }
}

// good
class App extends React.Component {
  constructor(props) {
    super(props);

    this.onClickDiv = this.onClickDiv.bind(this);
  }

  onClickDiv() {
    // do stuff
  }

  render() {
    return <div onClick={this.onClickDiv} />;
  }
}

四、基於路由的代碼分割
使用React.lazyReact Router來配置基於路由的代碼分割

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import React, { Suspense, lazy } from 'react';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Switch>
        <Route exact path="/" component={Home}/>
        <Route path="/about" component={About}/>
      </Switch>
    </Suspense>
  </Router>
);

參考資料

http://www.javashuo.com/article/p-ueqxqjhb-dz.html
http://www.javashuo.com/article/p-hiiezftc-do.html
http://www.javashuo.com/article/p-maytbjvw-kv.html
https://www.jianshu.com/p/333f390f2e84
https://yuchengkai.cn/docs/frontend/

相關文章
相關標籤/搜索