react扬帆起航之路由配置与组件分割

路由

react-router v4 发生了巨大改变,由静态路由开始转向动态路由,从此,就像使用普通组件一样来声明路由。其实,路由从此就是一个普通组件。

路由的按需加载的实质是代码分割,react-router官网有个代码拆分的示例,是基于bundle-loader实现的.现在官网的代码已经改为基于react-loadable实现。

除此之外,我们还可以通过dynamic import来实现代码分割,这里也是本文使用的方式。

首先,在项目根目录创建AsyncComponent.tsx:

// AsyncComponent.tsx
import * as React from 'react';

interface State {
  component: any;
}

const asyncComponent = (importComponent: any) => {

  class AsyncComponent extends React.Component<{}, State> {

    constructor(props: {}) {
      super(props);

      this.state = {
        component: null,
      };
    }

    async componentDidMount() {
      const { default: component } = await importComponent();

      this.setState({
        component: component
      });
    }

    render() {
      const C = this.state.component;

      return C
        ? 
        : 
loading...
; } } return AsyncComponent; }; export default asyncComponent;

然后,将需要分割的组件通过dynamic import引入后作为参数传递给 asyncComponent:

// App.tsx
import * as React from 'react';
import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-router-dom';
import asyncComponent from './AsyncComponent';
import HeaderComponent from './Header';

const App = () => {
  const AsyncHome = asyncComponent(() => import('./Home/Home'));
  const AsyncNotFound = asyncComponent(() => import('./NotFound'));

  return (
    
      
); }; export default App;

至此,我们完成了路由的按需加载。

基于react-loadable实现代码分割

按照上述方法,已经实现了代码分割。然而,react-loadable为我们提供了更好的解决方案。react-loadable核心实现原理也是通过dynamic import来实现组件的异步加载。在此基础上,它提供了更为强大的功能,如根据延迟时间确定是否显示loading组件、预加载、支持服务端渲染(关于与服务端渲染的搭配会在后续的文章中提到)等。

OK,现在将上述的App.tsx改造如下:

// App.tsx
import * as React from 'react';
import { Route, Redirect, Switch } from 'react-router-dom';
import * as Loadable from 'react-loadable';
import HeaderComponent from './Header';
import LoadingComponent from './Loading';

interface Props {
  pathname: string;
}

const AsyncHome = Loadable({
  loader: () => import(/* webpackChunkName: "homeChunk" */'./Home/Home'),
  loading: LoadingComponent,
  modules: ['homeChunk'],
  // home组件比设定的delay更长的时间加载的时候 => loading
  delay: 200, // 200ms
  // home组件比设定的timeout更长的时间加载的时候 => error
  timeout: 10000 // 10s
});

const AsyncNotFound = Loadable({
  loader: () => import(/* webpackChunkName: "notFoundChunk" */'./NotFound'),
  loading: LoadingComponent,
  modules: ['notFoundChunk'],
  delay: 200, // 200ms
  timeout: 10000 // 10s
});

const App = () => {

  return (
    
); }; export default App;

我们的loading组件如下:

//Loading.tsx
import * as React from 'react';

const LoadingComponent = (props: { [key: string]: string | any }) => {
  if (props.error) {
    return 

Error!

; } else if (props.timedOut) { return

Taking a long time...

; } else if (props.pastDelay) { return

Loading...

; } else { return null; } }; export default LoadingComponent;

关于react-loadable的预加载等功能的使用这里不再介绍,它的github页面提供了详细的介绍,有兴趣的读者可以自行了解下。

至此,路由配置与组件分割的内容完毕。


react扬帆启航专栏分享的时我个人学习与实践react过程中的一些历程,希望借此专栏与大家共同探讨react相关的技术,以求进步。

你可能感兴趣的:(react.js,react-router4,react-router)