咱们如今大多数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 手稿》