lazy
是react
提供的組件懶加載的能力,在官方沒有支持lazy
以前,在react
中咱們通常使用react-loadable
來實現組件懶加載的能力,可是,lazy
並不支持 服務端渲染(SSR
),因此在使用ssr的狀況下,lazy
暫時不能使用javascript
React.lazy
接受一個函數,這個函數內部調用 import()
動態導入。它必須返回一個 Promise
,該 Promise
須要 resolve
一個 defalut export
的 React
組件。html
具體如何使用呢,看下面例子java
import React, { lazy } from 'react'
const AppTitle = lazy(() => import('./title'))
class App extends React.Component {
render () {
return (
<AppTitle></AppTitle>
)
}
}
export default App
複製代碼
當咱們把這段代碼運行起來的時候,卻發現程序報錯了react
Error: A React component suspended while rendering, but no fallback UI was specified.
Add a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.
in Unknown (at lazy/index.jsx:8)
in App (at src/index.js:7)
複製代碼
這個時候就須要 react
中內置的組件 Suspense
來配合使用,只須要將 Suspense
引入,而後將異步導入的組件包裹起來,同時也要指定 fallback
屬性, 能夠支持傳入一段 jsx
, 或者一個組件實例,相似 <Loading></Loading>
webpack
import React, { lazy, Suspense } from 'react'
const AppTitle = lazy(() => import('./title.jsx'))
class App extends React.Component {
render () {
return (
<Suspense fallback={<div>Loading</div>}> <AppTitle></AppTitle> </Suspense>
)
}
}
export default App
複製代碼
當咱們使用 lazy
以後,咱們能夠打開 chrome
的 network
而後選擇 js
來觀察 發起的請求,咱們發現這個時候會出現 1.chunk.js
這種 數字開頭的js
文件,其實每一個 .js
就對應咱們每個組件,當咱們須要去 指定每一個 異步組件 打包的js
文件名時,咱們只須要在 import()
函數中 添加 /* webpackChunkName: "title" */
這段註釋,webpack 在打包時,自動會將咱們指定的名字做爲文件名git
import React, { lazy, Suspense } from 'react'
const AppTitle = lazy(
() => import(/* webpackChunkName: "title" */'./title.jsx')
)
class App extends React.Component {
render () {
return (
<Suspense fallback={<div>Loading</div>}> <AppTitle></AppTitle> </Suspense>
)
}
}
export default App
複製代碼
若是當一個組件異步加載下載js
文件時,網絡錯誤,沒法下載 js
文件,那麼 react
會表現出什麼狀況呢github
Error: Loading chunk 3 failed.
(error: http://192.168.4.183:3000/static/js/title.chunk.js)
複製代碼
很明顯,Suspense
沒法處理這種錯誤狀況, 在 react
中有一個 錯誤邊界 (Error Boundaries)
的概念,用來解決這種問題,它是利用了 react
生命週期的 componetDidCatch
方法來處理web
有兩種方式,一種是 生命週期 componentDidCatch
來處理錯誤,還有一種 是 靜態方法 static getDerivedStateFromError
來處理錯誤,chrome
官網的建議是性能優化
請使用 static getDerivedStateFromError() 渲染備用 UI ,使用 componentDidCatch() 打印錯誤信息。
import React, { lazy, Suspense } from 'react'
const AppTitle = lazy(
() => import(/* webpackChunkName: "title" */'./title.jsx')
)
class App extends React.Component {
state = {
isError: false
}
static getDerivedStateFromError(error) {
return { isError: true };
}
componentDidCatch (err, info) {
console.log(err, info)
}
render () {
if (this.state.isError) {
return (<div>error</div>)
}
return (
<div> <Suspense fallback={<div>Loading</div>}> <AppTitle></AppTitle> </Suspense> </div>
)
}
}
export default App
複製代碼
注意:使用 create-react-app
建立的項目,在開發環境,就算使用了 componentDidCatch
或者 getDerivedStateFromError
,錯誤依然會被拋出,在 build
後,錯誤將會捕獲,不會致使整個項目卸載
根據官方文檔所說,在 react 16
之後,任何未被錯誤邊界捕獲的錯誤將會致使整個 React
組件樹被卸載。 因此咱們在開發項目時,須要去捕獲錯誤邊界的錯誤,並提供一個備用UI
若是對你有幫助,點個贊吧