- Declare
Suspense
andfallback
import { Suspense } from 'react';
// 只需要使用一次Suspense
<Suspense fallback={Fallback}>
<Router>
...
</Router>
</Suspense>
- Use
lazy
to import components
// anywhere inside the Router
const MyComponent = React.lazy(() => import("./MyComponent"))
import Loadable from 'react-loadable'
const MyComponent = Loadable({
loader: () => import("./MyComponent"),
loading: Fallback
})
- Tie:
lazy
andSuspense
is embeded in React, no extra cost to import, but the size ofLoadable
is very small as well. - React wins:
1 suspense 1 fallback
vs1 loadable 1 fallback
- Loadable wins: You don't need
Suspense
for loadable - Loadable wins: Loadable gives more features like error handling, prefetch
Conclusion: Loadable is just an encapsulation of
lazy
andSuspense
- 假设有多个组件,都引入了
moment
这个包,单个组件设置moment
的lazy load,会使得moment
单独打成包吗?- 不会, 引入了
moment
的所有组件必须全部设置lazy load,才能实现这样的需求
- 不会, 引入了
- without hooks
const Calendar = (props: RouteComponentProps) => {
// 使用useState
const [time, setTime] = useState("0");
// 使用useEffect
useEffect(() => {
const init = async () => {
const module = await import('moment');
setTime(module.default().format())
};
init();
}, []);
return (
<div>
<br />
Calender: {time}
</div>
);
};
- with hooks
import { useState, useEffect } from 'react';
import { Moment } from 'moment'; // won't break spliting moment out, just types
const useMoment = () => {
const [moment, setMoment] = useState<Moment>();
useEffect(() => {
const getModule = async () => {
const module = await import('moment');
setMoment(module.default)
};
getModule();
}, []);
return [moment];
};
export default useMoment;
- merge
moment.js
andlodash.js
together, any chunkname you want
import(/* webpackChunkName: "my_lib" */ 'moment');
import(/* webpackChunkName: "my_lib" */ 'lodash');
if you want them
separate
, just remove the comments! Easy!
- You can now do lazy load on any modules
- 假设在引入moment的所有组件中全部实现了lazy load hooks,那一个页面引入moment后,进入其他页面,是不是还要重新request引入一次moment呢?
- 初步猜想: 不会, js文件会被浏览器缓存,不会重新request
- 首先, 通过
source-map-explorer
来分析bundle
组成,再分析大的module在组件中的使用情况 - 其次, 分析组件和module的对应关系, 一般来说
Component Split
就已经足够了
Component | Module | Code Split | Complexity | Note |
---|---|---|---|---|
1 | 1 | Component Split | Low | |
1 | n | Component Split | Low | Merge Package |
n | 1 | Module Split | High | avoid |
n | n | Module Split | High | avoid |
- 最后, 如果你像让多个module封装成一个chunk, 使用
/* webpackChunkName: "my_lib" */
这个webpack自带的magic comments功能
- 在后续项目开发中,对于非常大的包,要提前做好
lazy-load
分析和处理,在写代码的时候可以借助import cost
这个vscode extension
- 如有需要,可以使用
prefetch
预先在后台加载特定
的lib,可以让人感觉不到任何lazy-load
带来的延迟