Yapei Li

专注于前端领域

0%

React 代码拆分

代码拆分

打包

打包(Bundling) 是一个处理过程,跟踪导入的文件并将其合并到单个文件:“包” 。

然后,这个包文件可以包含到网页上,这样可以一次性加载整个应用程序。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// app.js
import { add } from './math.js';

console.log(add(16, 26)); // 42
// math.js
export function add(a, b) {
return a + b;
}

//打包后的包文件:
function add(a, b) {
return a + b;
}

console.log(add(16, 26)); // 42

代码拆分

代码拆分: 可以帮助你 “懒加载(lazy-load)” 用户当前需要的东西,这可以显著提高应用程序的性能。

虽然没有减少应用程序中的代码总量,但是已经避免了加载用户可能不需要的代码,并且减少了初始加载过程中的代码量。

import()

将代码拆分引入到应用程序中的最好方法是通过动态 import() 语法

Webpack 遇到这个语法时,它会自动启动 代码拆分 来拆分你的应用程

1
2
3
4
5
6
7
8
//之前:
import { add } from './math';
console.log(add(16, 26));

//以后:
import("./math").then(math => {
console.log(math.add(16, 26));
});

React.lazy

React.lazySuspense不可用于服务器端渲染

如果要在服务器渲染的应用程序中进行代码拆分,建议使用 Loadable Components

React.lazy 函数可以渲染动态导入为常规组件

React.lazy 接受一个函数,必须调用动态 import()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//之前:
import OtherComponent from './OtherComponent';

function MyComponent() {
return (
<div>
<OtherComponent />
</div>
);
}

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

function MyComponent() {
return (
<div>
<OtherComponent />
</div>
);
}

Suspense

如果在 MyComponent 渲染时尚未加载包含 OtherComponent 的模块,我们必须在等待加载时显示一些后备内容 - 例如加载指示符。 这是使用Suspense 组件完成的。

fallback prop(属性) 接受在等待加载组件时要渲染的任何 React 元素。

可以将 Suspense 组件放在惰性组件上方的任何位置。 甚至可以使用一个 Suspense 组件包装多个惰性组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//使用一个 Suspense 组件包装一个惰性组件
const OtherComponent = React.lazy(() => import('./OtherComponent'));

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

//使用一个 Suspense 组件包装多个惰性组件
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>
);
}

React.lazy 目前仅支持默认导出的组件export default ),如果想要导入的模块使用命名导出,则可以创建一个中间模块,将其重新导出为默认模块。

1
2
3
4
5
6
7
8
// 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"));

基于路由的代码拆分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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>
);