webpack4+react16+react-router-dom4从零配置到优化,实现路由按需加载(下)

上一篇介绍了下webpack的一些配置,接下来说下reactRouter4里面关于路由的一些配置,如何作到模块的按需加载,这也是经常使用的一种优化网站性能的方式。css

前言

react-router 仍是 react-router-dom?

首先在建立React项目的时候,咱们通常要引入两个包,react 和 react-dom, 那么 react-router 和react-router-dom 是否是两个都要引用呢?其实否则,二者只需取一,不一样之处就是后者比前者多出了 Link,BrowserRouter,HashRouter这样的 DOM 类组件。所以咱们只需引用 react-router-dom 这个包就好了。固然,若是搭配 redux ,你还须要使用 react-router-redux。 即便是在React Native中, 你也只须要引用react-router-native ,由于react-router-dom和react-router-native都是基于react-router的实现。react

实现步骤

1、安装

yarn  add react react-dom react-router-dom
复制代码

这里特别说明下:react版本问题,若是你安装的React是16.9以上版本,那么在你打开控制台的时候会出现如下警告:webpack

一年前,React 宣布 unsafe 生命周期方法重命名为:

  • componentWillMount → UNSAFE_componentWillMountweb

  • componentWillReceiveProps → UNSAFE_componentWillReceivePropsredux

  • componentWillUpdate → UNSAFE_componentWillUpdatebash

React v16.9 不包含破坏性更改,并且旧的生命周期方法在此版本依然沿用,仅此说明下babel

2、文件建立和babel

在这特别说明下.babelrc文件的做用: babel6.X版本以后,全部的插件都是可插拔的,也就是说只安装babel依然没法正常的工做,咱们须要配置对应的.babelrc文件才能起做用。react-router

.babelrc文件须要的配置项主要有预设(presets)和插件(plugins)。app

一、预设(presets)的做用是为babel安装指定的插件,插件命名采用babel-preset-xxx的形式;dom

二、presets是插件plugins的预设,也就是说直接须要不须要的插件一块儿引入,若是不想使用presets,能够单独使用plugins对某个功能进行单独的引入,有一些方法是presets中不提供的,若是要使用就须要单独引用了。

本人这里用的babel7,关于babel6和babel7的一些不一样点,能够参看下这个升级到Babel 7,里面讲的比较细致。

3、router按需加载的实现

在router4以前,咱们是使用getComponent的的方式来实现按需加载的,router4中,getComponent方法已经被移除,下面着重介绍一下react-router4是如何来实现按需加载的。

一、router3 的按需加载方式

route3中实现按需加载只须要按照下面代码的方式实现就能够了。

const Home = (location, callback) => {
  require.ensure([], require => {
    callback(null, require('../Component/Home').default)
  },'Home')
}
//配置route
<Route path="home" getComponent={Home} />
复制代码

二、router4:用create-react-app文档给的react-router按需加载实现

第一步:建立一个异步组件 src/components/AsyncComponent.js

import React from 'react';
export default function (componentFactory) {
  class AsyncComponent extends React.Component {
    constructor() {
      super();
      this.state = {component: null};
    }
    async componentDidMount() {
      let {default: component} = await componentFactory();
      this.setState({component});
    }
    render() {
      let Comp = this.state.component;
      return Comp ? <Comp {...this.props}/> : null;
    }
  }
  return AsyncComponent;
}
复制代码

第二步:将上面的组件导入router.js, 我这里是src/router/index.js

import React from "react";
import { Route, Switch } from "react-router-dom";
import asyncComponent from "../components/AsyncComponent";

const AsyncHome = asyncComponent(() => import("../pages/Home"));
const AsyncCount = asyncComponent(() => import("../pages/Count"));
const AsyncNotFound = asyncComponent(() => import("../pages/NotFound"));

export default ({ childProps }) =>
  <Switch>
    <Route
      path="/"
      exact
      component={AsyncHome}
      props={childProps}
    />
    <Route
      path="/count"
      exact
      component={AsyncCount}
      props={childProps}
    />
    {/* Finally, catch all unmatched routes */}
    <Route component={AsyncNotFound} />
  </Switch>;
复制代码

第三部:封装app根组件, 在scr/App.js下引入router.js

import React, { Component } from "react";
import { Link, withRouter } from "react-router-dom";
import Routes from "./router";
import './assets/reset.css';
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isAuthenticated: false,
      isAuthenticating: true
    };
  }
  render() {
    const childProps = {
      isAuthenticated: this.state.isAuthenticated,
      userHasAuthenticated: this.userHasAuthenticated
    };
    return (
        <Routes childProps={childProps} />
    );
  }
}
export default withRouter(App);

复制代码

第四部:将App组件放至入口文件index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom'
import App from './App';
// import registerServiceWorker from './components/registerServiceWorker';

ReactDOM.render(
  <BrowserRouter><App/></BrowserRouter>, 
  document.getElementById('app')
);
// registerServiceWorker();
复制代码

以上就是router4的按需加载 在这里补充另一种实现按需加载的方式:

三、router4: 利用react-loadable这个高级组件实现按需加载

yarn add react-loadable
复制代码
import React from 'react';
import { Router, Route, Switch } from 'react-router-dom';
import Loadable from 'react-loadable';

const MyLoadingComponent = ({ isLoading, error }) => {
  if (isLoading) {
    return null;
  }
  if (error) {
    return <div>Sorry, there was a problem loading the page.</div>;
  }
  return null;
};

const HomeItem = Loadable({
  loader: () => import('./pages/Home'),
  loading: MyLoadingComponent
});

const CountItem = Loadable({
  loader: () => import('./pages/Count'),
  loading: MyLoadingComponent
});


const Routes = ({ history }) => (
  <Router history={history}>
    <Layout>
      <Switch>
        <Route exact path="/" component={HomeItem} />
        <Route exact path="/count" component={CountItem} />
      </Switch>
    </Layout>
  </Router>
);
MyLoadingComponent.propTypes = {
  isLoading: PropTypes.bool,
  error: PropTypes.bool
};

MyLoadingComponent.defaultProps = {
  isLoading: true,
  error: false
};

Routes.propTypes = {
  history: PropTypes.object
};

Routes.defaultProps = {
  history: {}
};

export default Routes;
复制代码

以上是本人关于webpack4+react16+react-router-dom4从零配置到优化,实现路由按需加载的全部内容了,若是有疑问,或者不对的地方,欢迎你们在下方留言,一块儿探讨和更正。

webpack4+react16+react-router-dom4从零配置到优化,实现路由按需加载(上)

相关文章
相关标签/搜索