注意: 动态 import() 语法目前只是一个 ECMAScript (JavaScript) 提案, 而不是正式的语法标准。预计在不远的未来就会被正式接受。react
Webpack 解析到该语法时,它会自动地开始进行代码分割。若是你使用 Create React App,该功能已配置好,你能马上使用 这个特性。Next.js 也已支持该特性而无需再配置。 若是你本身配置 Webpack,你可能要阅读下 Webpack 关于代码分割的指南。你的 Webpack 配置应该相似于此。 当使用 Babel 时,你要确保 Babel 可以解析动态 import 语法而不是将其进行转换。对于这一要求你须要 babel-plugin-syntax-dynamic-import 插件。服务器
注意: React.lazy 和 Suspense 技术还不支持服务端渲染。若是你想要在使用服务端渲染的应用中使用,咱们推荐 Loadable Components 这个库。它有一个很棒的服务端渲染打包指南。babel
React.lazy 函数能让你像渲染常规组件同样处理动态引入(的组件)。网络
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div> <OtherComponent /> </div>
);
}
复制代码
这个函数他返回了一个Promise,须要用函数去调用,并且仍是主动抛错的,resolvereact-router
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const TowComponent = React.lazy(() => import('./TowComponent'))
function MyComponent() {
return (
<Suspense fallback={<div>Loading...</div>}> <OtherComponent /> <TowComponent /> </Suspense>
);
}
复制代码
那么 咱们继续问题,懒加载的组件,在加载的过程当中遇到一个问题如(网络问题)咱们该怎么样来维护用户体验呢?——不至于让用户看到空白 它会触发一个错误。你能够经过异常捕获边界**(Error boundaries)**dom
注意 错误边界仅能够捕获其子组件的错误,它没法捕获其自身的错误。若是一个错误边界没法渲染错误信息,则错误会冒泡至最近的上层错误边界,这也相似于 JavaScript 中 catch {} 的工做机制。异步
仍是上面代码:函数
import MyErrorBoundary from './MyErrorBoundary';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const TowComponent = React.lazy(() => import('./TowComponent'))
function MyComponent() {
return (
<MyErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
<TowComponent />
</Suspense>
<MyErrorBoundary>
);
}
复制代码
MyErrorBoundary 以下【选自官方文档】this
class MyErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// 更新 state 使下一次渲染可以显示降级后的 UI
return { hasError: true };
}
componentDidCatch(error, info) {
// 你一样能够将错误日志上报给服务器
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// 你能够自定义降级后的 UI 并渲染
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
export default MyErrorBoundary ;
复制代码
好让咱们回来 在SPA 单页面程序中,咱们可能要在多个页面中用到组件的懒加载,这样的话咱们就能够吧他定义在路由中 很简单 套进去就能够了spa
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>
);
复制代码
接下来咱们就会想了,既然是import
那是否是也能够向导入组件那种 进行 重命名
错误示范
const Tow = React.lazy(() => import('./TowComponent'))
复制代码
注意:不能够直接这样子作 ,eact.lazy 目前只支持默认导出(default exports)。若是你想被引入的模块使用命名导出(named exports),你能够建立一个中间模块,来从新导出为默认模块。这能保证 tree shaking 不会出错,而且没必要引入不须要的组件。
// 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"));
复制代码
可是 真的有必要这样子作吗?