基于 create react app路由4.0的異步元件加載
本文章是一個額外的篇章,它可以在你的react
app中,幫助加快初始的加載元件時間。當然這個操作不是完全必要的,但如果你好奇的話,請随意跟随這篇文章一起用create react app和
react路由4.0的異步加載方式來幫助react.js建構大型應用。
代碼分割(code splitting)
當我們用react.js寫我們的單頁應用程式時候,這個應用會變得越來越大,一個應用(或者路由頁面)可能會引入大量的元件,可是有些元件是第一次加載的時候是不必要的,這些不必要的元件會浪費很多的加載時間。
你可能會注意到 create react app
在打包完畢之後會生成一個很大的.js檔案,這包含了我們應用程式需要的所有javascript。但是,如果使用者隻是加載登入頁面去登入網站,我們加載應用程式的其餘部分是沒有意義的。在我們的應用程式還很小的時候,這并不是一個問題,但是它卻是我們程式猿優化的一個東西。為了解決這個問題,create
react app有一個非常簡單的代碼分割的的方案。
代碼分割和 react-router
在我們 react app 中,常見的路由配置可能是像下面一樣的
/* 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>
);
我們一開始引入這些元件,然後定義好的路徑,會根據我們的路由去比對這些元件。
但是,我們靜态地在頂部導入路由中的所有元件。這意味着,不管哪個路由比對,所有這些元件都被加載。我們隻想加載對比對路由的時候才加載響應的元件。下面我們一步步來完成這個使命。
建立一個異步元件
建立一個js 檔案,如:src/components/asynccomponent.js,代碼如下
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;
}
我們在這裡做了一些事情:
這個asynccomponent 函數接受一個importcomponent 的參數,importcomponent 調用時候将動态引入給定的元件。
在componentdidmount 我們隻是簡單地調用importcomponent 函數,并将動态加載的元件儲存在狀态中。
最後,如果完成渲染,我們有條件地提供元件。在這裡我們如果不寫null的話,也可提供一個菊花圖,代表着元件正在渲染。
使用異步元件
現在讓我們使用我們的異步元件,而不是像開始的靜态去引入。
我們要用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 }) => (
<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} />
隻需幾次更改就相當酷了。我們的app都是設定了代碼分割而的。也沒有增加太多的複雜性。
這裡我們看看之前的這個src/routes.js路由檔案
import login from './containers/login';
import notes from './containers/notes';
import signup from './containers/signup';
import newnote from './containers/newnote';
<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} />
注意,不要在頂部的引入所有的元件。我們正在建立這些代碼分割的功能,以便在必要時為我們進行動态導入。
現在你運作npm run build 您将看到代碼已經被分割成一個個小檔案。
下面是部署好的在網站的真實截圖
每個.chunk.js都是需要的時候才加載的。當然我們的程式是相當小的,并且分離在各個部分的小元件,是不需要這樣子按需加載的。還是看你項目的需求。
作者:佚名
來源:51cto