- Declare Suspenseandfallback
import { Suspense } from 'react';
// 只需要使用一次Suspense
<Suspense fallback={Fallback}>
  <Router>
  ...
  </Router>
</Suspense>  - Use lazyto 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: lazyandSuspenseis embeded in React, no extra cost to import, but the size ofLoadableis very small as well.
- React wins: 1 suspense 1 fallbackvs1 loadable 1 fallback
- Loadable wins: You don't need Suspensefor loadable
- Loadable wins: Loadable gives more features like error handling, prefetch
Conclusion: Loadable is just an encapsulation of
lazyandSuspense
- 假设有多个组件,都引入了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.jsandlodash.jstogether, 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带来的延迟