上一篇介紹了下webpack的一些配置,接下來說下reactRouter4裏面關於路由的一些配置,如何作到模塊的按需加載,這也是經常使用的一種優化網站性能的方式。css
首先在建立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
yarn add react react-dom react-router-dom
複製代碼
這裏特別說明下:react版本問題,若是你安裝的React是16.9以上版本,那麼在你打開控制檯的時候會出現如下警告:webpack
componentWillMount → UNSAFE_componentWillMountweb
componentWillReceiveProps → UNSAFE_componentWillReceivePropsredux
componentWillUpdate → UNSAFE_componentWillUpdatebash
React v16.9 不包含破壞性更改,並且舊的生命週期方法在此版本依然沿用,僅此說明下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,裏面講的比較細緻。
在router4以前,咱們是使用getComponent的的方式來實現按需加載的,router4中,getComponent方法已經被移除,下面着重介紹一下react-router4是如何來實現按需加載的。
route3中實現按需加載只須要按照下面代碼的方式實現就能夠了。
const Home = (location, callback) => {
require.ensure([], require => {
callback(null, require('../Component/Home').default)
},'Home')
}
//配置route
<Route path="home" getComponent={Home} />
複製代碼
第一步:建立一個異步組件 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的按需加載 在這裏補充另一種實現按需加載的方式:
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從零配置到優化,實現路由按需加載的全部內容了,若是有疑問,或者不對的地方,歡迎你們在下方留言,一塊兒探討和更正。