咱們如今大多數React
項目都是以Webpack
或者 Browserify
等將一堆的jsx文件組織一塊兒,而且由一個相似index.js
的入口文件串聯起來的單頁面web
頁面。react
例如:git
// math.js export function add(a, b) { return a + b; }
App:github
// app.js import { add } from './math.js'; console.log(add(16, 26)); // 42
打完包後:web
function add(a, b) { return a + b; } console.log(add(16, 26)); // 42
從這個例子能夠看出,打完包後將全部的js都壓縮到一個文件裏了。隨着項目愈來愈大,打包的文件也會愈來愈大,若是再引入一些第三方的js
庫,那就更龐大了。babel
接下來介紹一下如何將React
代碼分隔。(如下內容是16.6.0版本才支持的)react-router
Code Splitting
會幫助你的應用實現lazy load
.app
這麼作,即便沒有減小整個項目的代碼量,也會避免在項目初始加載時,加載沒必須的js
,從而使用項目性能有所提高。dom
最簡單直接的方式就是引入動態 import
實現代碼分隔。性能
使用 動態 import
以前:code
import { add } from './math'; console.log(add(16, 26));
使用動態 import
後:
import("./math").then(math => { console.log(math.add(16, 26)); });
注意,動態import
並非標準的EcmaScript,因此須要配置babel-plugin-syntax-dynamic-import
React.lazy
能夠以一個React標準組件的方法渲然一個動態引入的組件。
之前的作法:
import OtherComponent from './OtherComponent'; function MyComponent() { return ( <div> <OtherComponent /> </div> ); }
使用 React.lazy
:
const OtherComponent = React.lazy(() => import('./OtherComponent')); function MyComponent() { return ( <div> <OtherComponent /> </div> ); }
這樣在組件MyComponent
渲然的時候才加載OtherComponent
。
React.lazy
必須使用動態 import()
引入組件,必須返回一個 Promise Component
。
React.lazy
目前不支持服務端渲然
假如在 React.lazy
時,import
失敗或者異常時,咱們須要給於提示,或者一個默認的組件,咱們就須要使用 Suspense
.
例如:
const OtherComponent = React.lazy(() => import('./OtherComponent')); function MyComponent() { return ( <div> <Suspense fallback={<div>Loading...</div>}> <OtherComponent /> </Suspense> </div> ); }
fallback
也是一個組件,但不能經過 動態 import
引入的組件.
Suspense
只能包裹一個單結點,若是有多個 動態 import
的組件須要放在一個 Suspense
中時,可使用相似 React.Fragmet
包裹一下,也可使用其餘的 React
組件包裹。例如:
const OtherComponent = React.lazy(() => import('./OtherComponent')); const AnotherComponent = React.lazy(() => import('./AnotherComponent')); function MyComponent() { return ( <div> <Suspense fallback={<div>Loading...</div>}> <section> <OtherComponent /> <AnotherComponent /> </section> </Suspense> </div> ); }
基於 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> );
React.lazy
目前只支持 default
導出,不支持命名導出。例如,只支持:
export default () => { return(<div>I am a Lazy component</div>); }
若是要支持命令導出,須要從新再 export
,例如:
// ManyComponents.js export const MyComponent = /* ... */; export const MyUnusedComponent = /* ... */;
// MyComponent.js export { MyComponent as default } from "./ManyComponents.js";
// MyApp.js import React, { lazy } from 'react'; const MyComponent = lazy(() => import("./MyComponent.js"));
推薦閱讀 《React 手稿》