在上一次開發一個大型的SPA網站的時候,由於加載了大量的第三方庫,致使webpack打包出來的bundle.js異常的大,時候祭出了code splite來減小js的大小了。所謂的Code splite其實就是所謂js的懶加載。由於咱們的技術棧使用react + redux + redux-thunk配合create-react-app來搭建的,因此咱們就說說Create React App如何來作代碼分割。html
首先須要申明的是代碼分割不是一顆銀彈,不要過分優化你的程序除非你的程序到了須要優化的程度,或者想我這樣就是想瞎折騰學習學習。若是在開發React過程當中發現打包出來的bundle.js愈來愈大,多半是和咱們同樣引入了不少組件致使程序在第一次加載的過慢。react
思考如下以下的場景:在用戶使用一個比較大的程序,當用戶只是在登陸界面,沒有必要將整個程序都加載出來。Create React App起始已經內置了代碼分割功能來動態加載import。Import來動態加載組件一般配合React Router。咱們經過設置React Router來根據Url路徑來作到按需加載組件。webpack
代碼分割其實加載的一個模塊,require/export出生在野生規範,被普遍使用在CommonJS、AMD、CMD等等, import/export則是名門正派由ECMAScript版本進來。git
本質的差異:github
首先咱們建立一個包裝的Async Component。web
import React, {Component} from 'react';
export default function asyncComponent(importComponent) {
class AsyncComponent extends Component {
constructor(props) {
super(props);
this.setState(component : null)
}
async componentDidMount() {
const {default: component} = await importComponent();
this.setState({component: component})
}
render() {
const C = tis.state.component;
return C
? <C {...this.props}/> : null } } return AsyncComponent; } 複製代碼
以前咱們都是靜態的加載組件npm
import Home from './containers/Home';
複製代碼
如今咱們使用 asyncComponent來動態加載咱們須要的組件redux
const AsyncHome = asyncComponent(() => import ('./container/Home'))
複製代碼
比較二者的區別,咱們會發如今動態加載起始咱們只是包裝了一個函數,將一個函數傳入,當包裝的函數加載完成後在生命週期的componentDidMount()來import咱們真正須要的組件。react-router
而後咱們來看看將組件使用在routesapp
以前咱們是直接加載的靜態組件
<Route path = '/' exact component = {Home}/>
// <Route path = '/' exact component = {AsyncHome}/>
複製代碼
import React from "react";
import { Route, Switch } from "react-router-dom";
import asyncComponent from "./components/AsyncComponent";
import AppliedRoute from "./components/AppliedRoute";
import AuthenticatedRoute from "./components/AuthenticatedRoute";
import UnauthenticatedRoute from "./components/UnauthenticatedRoute";
const AsyncHome = asyncComponent(() => import("./containers/Home"));
const AsyncLogin = asyncComponent(() => import("./containers/Login"));
const AsyncNotes = asyncComponent(() => import("./containers/Notes"));
const AsyncSignup = asyncComponent(() => import("./containers/Signup"));
const AsyncNewNote = asyncComponent(() => import("./containers/NewNote"));
const AsyncNotFound = asyncComponent(() => import("./containers/NotFound"));
export default ({ childProps }) =>
<Switch>
<AppliedRoute
path="/"
exact
component={AsyncHome}
props={childProps}
/>
<UnauthenticatedRoute
path="/login"
exact
component={AsyncLogin}
props={childProps}
/>
<UnauthenticatedRoute
path="/signup"
exact
component={AsyncSignup}
props={childProps}
/>
<AuthenticatedRoute
path="/notes/new"
exact
component={AsyncNewNote}
props={childProps}
/>
<AuthenticatedRoute
path="/notes/:id"
exact
component={AsyncNotes}
props={childProps}
/>
{/* Finally, catch all unmatched routes */}
<Route component={AsyncNotFound} />
</Switch>
複製代碼
經過運行npm run build 咱們會看到 代碼切割的js 分別是 build/static.js/1.chunk.js 之類的,說明咱們已經已經完成了代碼切割。
若是你講上面的asyncComponent放入了線上環境頗有可能會被主觀打死,由於上面的代碼僅供參考,由於是異步加載因此有不少異常的corner case沒有考慮在其中。其實已經有大神給咱們寫好的react-loadable,使用起來至關方便,再次我也不在贅述了。