[譯] 延遲加載 React Components (用 react.lazy 和 suspense)

原文: blog.bitsrc.io/lazy-loadin…javascript

雖然在 React 16.8.1 中終於面世的 hooks 引人矚目,但在去年發佈的 16.6.0 版本里也包含了一個吸引人的新特性,可讓咱們在不依賴第三方庫的狀況下簡化對延遲加載(lazy loading)的處理。css

讓咱們看看如何藉助這個特性改善應用性能,並構建更好的用戶體驗。java

按照過往的經驗,在構建組件的時候,將其用相似 Bit 的工具概括起來是頗有用的 -- 能夠分享你的組件並在任意應用中使用之,以加速開發並保持 DRY 原則。node

React.lazy() 是什麼?

這項新功能使得能夠不借助任何附加庫就能經過代碼分割(code splitting)延遲加載 react 組件。延遲加載是一種優先渲染必須或重要的用戶界面項目,而將不重要的項目悄然載入的技術。這項技術已經被徹底整合進了 react 自身的核心庫中。以前咱們要用 react-loadable 達到這一目的,但如今用 react.lazy() 就好了。react

Suspense 掛起組件

Suspense 是一個延遲函數所必須的組件,一般用來包裹住延遲加載組件。多個延遲加載的組件可被包在一個 suspense 組件中。它也提供了一個 fallback 屬性,用來在組件的延遲加載過程當中顯式某些 react 元素。webpack

延遲和掛起爲什麼重要?

首先,打包工具將全部代碼組件相繼概括到一個 javascript 塊中,並將其傳遞給瀏覽器;但隨着應用增加,咱們注意到打包的體積也與日俱增。這會致使應用由於加載慢而難以使用。藉助代碼分割,代碼包能被分割成更小的塊,最重要的塊先被加載,而其他次要的則延遲加載。git

同時,咱們知道構建應用的一個最佳實踐是:應該考慮到用戶在使用移動互聯網數據和其餘慢速網絡鏈接時的狀況。做爲開發者就應該在哪怕是在資源讀取到 DOM 中的掛起階段也能控制好用戶體驗。github

起步

根據 react 官方文檔,若是使用了下列技術,那麼就已經有 webpack 打包配置了:web

  • CRA (create react app)
  • Next js
  • Gatsby

若是沒有的話,就須要本身設置打包了。好比,讀一下 Webpack 官方文檔中的 InstallationGetting Startednpm

Demo

咱們用 create-react-app 建立一個 react 應用,並在裏面實現帶掛起的延遲加載,它將用來顯示 MTV Base 上 2019 上頭牌藝人的專輯名和專輯數量。我用 create-react-app 建立了一個乾淨的應用,幷包含了一個咱們能夠在本例中用得上的簡易組件。

  • 克隆 gitlab.com/viclotana/r…
  • 解壓文件並打開一個終端窗口
  • 在解壓出的文件的根目錄下安裝項目的 node modules 依賴
  • 用如下命令啓動開發服務器:
$ sudo npm start
複製代碼

Sample Application

就是這麼個簡單的應用,藝人的數據被從應用中的一個 store 中讀出。固然你也能夠本身編寫這些代碼,應用的 src 下面應該有這些文件:

  1. Artists.js
import React from ‘react’;
import ‘./App.css’;
import artists from 「./store」;
export default function Artists(){
 return (
   <> <h1>MTV Base Headline Artists 2019</h1> {artists.map(artist =>( <div id=」card-body」 key={artist.id}> <div className=」card」> <h2>{artist.name}</h2> <p>genre: {artist.genre}</p> <p>Albums released: {artist.albums}</p> </div> </div> ))} </> ); } 複製代碼
  1. Store.js
export default [
{
  id: 「1」,
  name: 「Davido」,
  country: 「Nigeria」,
  genre: 「Afro-Pop」,
  albums: 「2」
},
{
  id: 「2」,
  name: 「AKA」,
  country: 「South-Africa」,
  genre: 「Hip-Hop」,
  albums: 「4」
},
{
  id: 「3」,
  name: 「Seyi Shay」,
  country: 「Nigeria」,
  genre: 「R&B」,
  albums: 「2」
},
{
  id: 「4」,
  name: 「Sauti Sol」,
  country: 「Kenya」,
  genre: 「Soul」,
  albums: 「3」
}
];
複製代碼
  1. Index.js
import React from ‘react’;
import ReactDOM from ‘react-dom’;
import ‘./index.css’;
import Artists from ‘./Artists’;
class App extends React.Component {
 render(){
  return(
   <div className=」App」> <Artists /> </div>
   );
 }
}
ReactDOM.render(<App />, document.getElementById(‘root’)); 複製代碼
  1. App.css
.App {
 text-align: center;
}
h1 {
 padding: 30px;
}
#card-body {
 display: inline-flex;
 padding: 10px;
 margin: 30px 30px;
 border: 5px solid rgb(93, 171, 207);
 border-radius: 8px;
 background: lightblue;
}
複製代碼

如今讓咱們看看如何用 react.lazy 及 suspense 去處理藝人組件的延遲加載。

  • index.js 的頭部引入 react 中的 lazy 和 suspense:
import { Suspense, lazy } from 'react';
複製代碼
  • 要像常規組件同樣渲染一個動態引入的組件,使用 react 文檔中提供的 react.lazy 函數語法,以下:
const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div> <OtherComponent /> </div>
  );
}
複製代碼
  • 應用到咱們的藝人組件上:
const Artists = React.lazy(() => import('./Artists'));

function MyComponent() {
  return (
    <div> <Artists /> </div>
  );
}
複製代碼

若在 App 組件渲染期間,包含藝人組件的模塊沒有加載完,就必須顯示一些提示等待的 fallback 內容 -- 好比一個加載指示器,下面是用 Suspense 組件完成這一目的的語法:

const OtherComponent = React.lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <div> <Suspense fallback={<div>Loading...</div>}> <OtherComponent /> </Suspense> </div>
  );
}
複製代碼

應用到藝人組件上:

const Artists = React.lazy(() => import('./Artists'));

function MyComponent() {
  return (
    <div> <Suspense fallback={<div>Loading...</div>}> <Artists /> </Suspense> </div>
  );
}
複製代碼

把以上拼在一塊兒, index.js 看起來是這樣的:

import React, { lazy, Suspense } from ‘react’;
import ReactDOM from ‘react-dom’;
import ‘./index.css’;
// import Artists from ‘./Artists’;
const Artists = lazy(() => import(‘./Artists’))
class App extends React.Component {
 render(){
  return(
   <div className=」App」> <Suspense fallback={<h1>Still Loading…</h1>}> <Artists /> </Suspense> </div>
  );
 }
}
ReactDOM.render(<App />, document.getElementById(‘root’)); 複製代碼

在你的 localhost 上應該運行的很快,以致於你根本感受不到有什麼改變。但你能夠建立一段時間統計代碼,或模擬慢速網絡:

  • 打開瀏覽器的 dev tools
  • 選擇 network tab
  • 點擊右側遠端的 online tab,顯示其餘選項(最右側的下箭頭)
  • 選擇 fast 3G

如今刷新瀏覽器就能看到延遲加載如何發生了...

Still Loading…

多個延遲加載組件

那麼再快速添加一個渲染標題的小組件,看看 react.lazy 如何仍只用一個 suspense 組件處理:

建立 performers.js 文件:

mport React from ‘react’;
import ‘./App.css’;
export default function Performers(){
 return (
  <> <h2>These are the MTV Base Headline Artists...</h2> </> ); } 複製代碼

並在 index.js 中添加一行延遲加載代碼:

import React, { lazy, Suspense } from ‘react’;
import ReactDOM from ‘react-dom’;
import ‘./index.css’;
const Artists = lazy(() => import(‘./Artists’))
const Performers = lazy(() => import(‘./Performers’))
class App extends React.Component {
 render(){
  return(
   <div className=」App」> <Suspense fallback={<h1>Still Loading…</h1>}> <Artists /> <Performers /> </Suspense> </div>
  );
 }
}
ReactDOM.render(<App />, document.getElementById(‘root’)); 複製代碼

如今,在 suspense 中的佔位符元素渲染以後,兩個延遲加載的組件便馬上顯示出來了。

The two lazy components loaded within one suspense

這和 loadable 中必須爲每一個延遲加載組件都弄個 loading 是不一樣的。

⚠️ 重要提示

React.lazy 和 Suspense 在服務端渲染中尚不可用。若是想在服務器渲染的應用中使用代碼分割,Loadable 組件還是強烈推薦的,在其文檔中有很好相關解釋。

總結

咱們看到了如何用 react 提供的 lazy 和 suspense 組件實現延遲加載。和這個新特性帶來的衆多可能性相比,以上例子過於基礎。你能夠在本身的項目中靈活應用,編碼愉快!



--End--

搜索 fewelife 關注公衆號

轉載請註明出處

相關文章
相關標籤/搜索