code splite之react-loadable

210 阅读2分钟

code-splite有两种实现方式:

  • 基于组件的code spliting
  • 基于路由的code spliting

一个路由对应的其实就是一个组件,并没有什么特别,如果是基于路由的code spliting,那么切分的粒度会是路由级别的。

如果基于组件的code spliting,那么切分的粒度是组件级的,也就是说基于组件的代码分割粒度更细,可以对Modal、tabs以及其他的UI 组件都进行代码分割

基于组件的code spliting 相比于 基于路由的code spliting 的另一个好处是性能更好

考虑以下场景:

  1. 页面中有一个选项卡中隐藏了一个地图组件,当用户没有点击该选项卡,不需要加载这个巨大的地图组件
  2. 对于一些可以推迟加载的内容,不需要和高优先级的组件同时加载,例如:在页面底部的内容组件,它们不需要和顶部的组件同时加载,可以推迟到页面展示这些组件时才进行加载

react-loadable使用基于组件的code spliting 更容易实现,总的来说,react-loadable是一个用于动态加载组件的库,虽然,可以使用es6的 dynamic import 来实现动态加载组件,但是使用react-loadable可以做的更好,提供了更加丰富以及贴近业务的特性,如:

  • 加载失败的处理
  • 加载超时的处理
  • 加载中的状态处理,常见的有在加载中时,展示一个loading
  • 延迟展示加载中的状态
  • 服务端的处理方式

因此,使用react-loadable作为动态加载组件更合适

loading组件定义:

import Loadable from 'react-loadable';
import Spin from './components/spin';
import React, { Component } from 'react';

export const Loading = props => {
  if (props.error) {
    // props.retry&&props.retry();
    !__LOCAL__&&window.location.reload();
    // eslint-disable-next-line no-console
    console.log(props.error)
    return <div >加载失败</div>
  } else if (props.timedOut) {
    // props.retry&&props.retry();
    !__LOCAL__&&window.location.reload();
    return <div >加载超时</div>
  } else if (props.pastDelay) {
    return <Spin />
  }
  return null
};


export const importPath = ({loader}) => {
  return  Loadable({
    loader,
    loading:Loading,
    delay: 200,
    timeout: 200000,
  })
}

与react-router配合:

import { importPath } from './loadable';

let router = [
  {
    path: '/',
    exact: true,
    component:importPath({
      loader: () => import(/* webpackChunkName:"home" */ "pages/home.tsx"),
    }),
  },
  {
    path: '/order',
    exact: true,
    component:importPath({
      loader: () => import(/* webpackChunkName:"" */ "pages/order"),
    }),
  }
]