代码拆分(Code-Splitting)
打包(Bundling)
大多数的 React 应用程序使用Webpack或 Browserify 等工具来 “打包” 文件。打包(Bundling) 是一个处理过程,跟踪导入的文件并将其合并到单个文件:“包” 。然后,这个包文件可以包含到网页上,这样可以一次性加载整个应用程序。
示例
App:
// 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
注意:
你的最终包文件,看起来不同于这个。
如果你使用的是Create React App,Next.js,Gatsby 或类似的工具,您将拥有一个开箱即用的 Webpack 安装程序来打包你的应用程序。
如果你没用使用这些工具,你需要自己安装 Webpack 。 例如,请参阅Webpack文档上的安装 和 入门 指南。
代码拆分
打包工具非常强大,但是随着你的应用的增长,你的包文件也会增长。特别是如果你引用了大型的第三方库。你需要密切关注包含在你包文件中的代码,这样你就不会意外地把它弄得太大,以至于你的应用程序需要很长时间才能加载完成。
为了避免生成一个很大的包文件,最好事先解读这个问题,开始拆分你的包文件。Code-Splitting 是很多打包工具都支持的特性,比如 Webpack 和 Browserify (通过 factor-bundle ),它可以创建多个包文件,可以在运行时动态加载。
代码拆分 你的应用程序可以帮助你 “懒加载(lazy-load)” 用户当前需要的东西,这可以显着提高您的应用程序的性能。虽然你没有减少应用程序中的代码总量,但是你已经避免了加载用户可能不需要的代码,并且减少了初始加载过程中的代码量。
import()
将代码拆分引入到应用程序中的最好方法是通过动态 import()
语法。
之前:
import { add } from './math';
console.log(add(16, 26));
以后:
import("./math").then(math => {
console.log(math.add(16, 26));
});
Note:
动态
import()
语法是ECMAScript(JavaScript)提案,目前不是语言标准的一部分。预计在不远的将来会被接受。
当 Webpack 遇到这个语法时,它会自动启动 代码拆分 来拆分你的应用程序。 如果您正在使用 Create React App ,则已经为你配置好了,你可以立即开始使用它。 在 Next.js 中,它也支持开箱即用。
如果你是自己设置 Webpack ,你可能需要阅读 Webpack 关于 代码拆分的指南。 你的 Webpack 配置应该看起来类似于 这样 。
在使用 Babel 时,你需要确保 Babel 能够解析动态导入语法,但目前 Babel 还不能直接对其进行转换。 为此,你需要使用 babel-plugin-syntax-dynamic-import。
库(Libraries)
React Loadable
React Loadable 包装一个很好的、React友好 动态导入 API,用于在给定组件中,将代码拆分引入到你的应用程序中。
之前:
import OtherComponent from './OtherComponent';
const MyComponent = () => (
<OtherComponent/>
);
之后:
import Loadable from 'react-loadable';
const LoadableOtherComponent = Loadable({
loader: () => import('./OtherComponent'),
loading: () => <div>Loading...</div>,
});
const MyComponent = () => (
<LoadableOtherComponent/>
);
React Loadable 可以帮助您创建 loading states, error states, timeouts, preloading,等等。它甚至可以帮助 服务端渲染 一个具有大量 代码拆分 的应用程序。
基于路由的代码拆分
决定在应用程序中引入 代码拆分 的位置可能有点棘手。您需要确保选择的位置可以将 拆分包 均匀分配,但不会破坏用户体验。
路由开始处是一个好的地方。网上的大多数人都习惯于页面过度,知道页面需要花费一定的时间来加载。你也倾向于一次重新渲染整个页面,因此你的用户不可能同时与页面上的其他元素进行交互。
这里有一个例子,说明如何设置基于路由器的代码,使用诸如React Router之类的库来分割到应用程序,并对其进行响应。
以下是如何使用 React Router 和React Loadable 等库设置基于路由的 代码拆分 来拆分你的应用程序的示例。
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Loadable from 'react-loadable';
const Loading = () => <div>Loading...</div>;
const Home = Loadable({
loader: () => import('./routes/Home'),
loading: Loading,
});
const About = Loadable({
loader: () => import('./routes/About'),
loading: Loading,
});
const App = () => (
<Router>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
</Switch>
</Router>
);