本文章是一個額外的篇章,它能夠在你的React app
中,幫助加快初始的加載組件時間。固然這個操做不是徹底必要的,但若是你好奇的話,請隨意跟隨這篇文章一塊兒用Create React App
和 react路由4.0
的異步加載方式來幫助react.js
構建大型應用。html
當咱們用react.js
寫咱們的單頁應用程序時候,這個應用會變得愈來愈大,一個應用(或者路由頁面)可能會引入大量的組件,但是有些組件是第一次加載的時候是沒必要要的,這些沒必要要的組件會浪費不少的加載時間。react
你可能會注意到 Create React App
在打包完畢以後會生成一個很大的.js
文件,這包含了咱們應用程序須要的全部JavaScript
。可是,若是用戶只是加載登陸頁面去登陸網站,咱們加載應用程序的其他部分是沒有意義的。在咱們的應用程序還很小的時候,這並非一個問題,可是它倒是咱們程序猿優化的一個東西。爲了解決這個問題,Create React App
有一個很是簡單的代碼分割的的方案。git
在咱們 react app
中,常見的路由配置多是像下面同樣的github
/* Import the components */ import Home from './containers/Home'; import Posts from './containers/Posts'; import NotFound from './containers/NotFound'; /* Use components to define routes */ export default () => ( <Switch> <Route path="/" exact component={Home} /> <Route path="/posts/:id" exact component={Posts} /> <Route component={NotFound} /> </Switch> );
咱們一開始引入這些組件,而後定義好的路徑,會根據咱們的路由去匹配這些組件。npm
可是,咱們靜態地在頂部導入路由中的全部組件。這意味着,無論哪一個路由匹配,全部這些組件都被加載。咱們只想加載對匹配路由的時候才加載響應的組件。下面咱們一步步來完成這個使命。react-router
建立一個js 文件,如:src/components/AsyncComponent.js
,代碼以下app
import React, { Component } from "react"; export default function asyncComponent(importComponent) { class AsyncComponent extends Component { 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 ? <C {...this.props} /> : null; } } return AsyncComponent; }
咱們在這裏作了一些事情:less
這個asyncComponent
函數接受一個importComponent
的參數,importComponent
調用時候將動態引入給定的組件。dom
在componentDidMount
咱們只是簡單地調用importComponent
函數,並將動態加載的組件保存在狀態中。異步
最後,若是完成渲染,咱們有條件地提供組件。在這裏咱們若是不寫null
的話,也可提供一個菊花圖,表明着組件正在渲染。
如今讓咱們使用咱們的異步組件,而不是像開始的靜態去引入。
import Home from './containers/Home';
咱們要用asyncComponent
組件來動態引入咱們須要的組件。
tip: 別忘記 先
import asyncComponent from './AsyncComponent
const AsyncHome = asyncComponent(() => import('./containers/Home'));
咱們將要使用 AsyncHome
這個組件在咱們的路由裏面
<Route path="/" exact component={AsyncHome} />
如今讓咱們回到Notes項目並應用這些更改。
src/Routes.js
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> );
只需幾回更改就至關酷了。咱們的app都是設置了代碼分割而的。也沒有增長太多的複雜性。
這裏咱們看看以前的這個src/Routes.js
路由文件
import React from 'react'; import { Route, Switch } from 'react-router-dom'; import AppliedRoute from './components/AppliedRoute'; import AuthenticatedRoute from './components/AuthenticatedRoute'; import UnauthenticatedRoute from './components/UnauthenticatedRoute'; import Home from './containers/Home'; import Login from './containers/Login'; import Notes from './containers/Notes'; import Signup from './containers/Signup'; import NewNote from './containers/NewNote'; import NotFound from './containers/NotFound'; export default ({ childProps }) => ( <Switch> <AppliedRoute path="/" exact component={Home} props={childProps} /> <UnauthenticatedRoute path="/login" exact component={Login} props={childProps} /> <UnauthenticatedRoute path="/signup" exact component={Signup} props={childProps} /> <AuthenticatedRoute path="/notes/new" exact component={NewNote} props={childProps} /> <AuthenticatedRoute path="/notes/:id" exact component={Notes} props={childProps} /> { /* Finally, catch all unmatched routes */ } <Route component={NotFound} /> </Switch> );
注意,不要在頂部的引入全部的組件。咱們正在建立這些代碼分割的功能,以便在必要時爲咱們進行動態導入。
如今你運行npm run build
您將看到代碼已經被分割成一個個小文件。
下面是部署好的在網站的真實截圖
每一個.chunk.js
都是須要的時候才加載的。固然咱們的程序是至關小的,而且分離在各個部分的小組件,是不須要這樣子按需加載的。仍是看你項目的需求。