Create React App中的代碼分割實踐

Code Splite

在上一次開發一個大型的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

JS的模塊化規範

代碼分割其實加載的一個模塊,require/export出生在野生規範,被普遍使用在CommonJS、AMD、CMD等等, import/export則是名門正派由ECMAScript版本進來。git

本質的差異:github

  • CommonJS仍是ES6 Module輸出均可以當作是一個具有多個屬性或者方法的對象
  • default是ES6 Module所獨有的關鍵字,export default fs輸出默認的接口對象
  • ES6 module中導入模塊的屬性或者方法是強綁定,包括基礎類型,而CommonJS則是普通的值傳遞或者引用傳遞。

Async Component

首先咱們建立一個包裝的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 之類的,說明咱們已經已經完成了代碼切割。

react-loadable

若是你講上面的asyncComponent放入了線上環境頗有可能會被主觀打死,由於上面的代碼僅供參考,由於是異步加載因此有不少異常的corner case沒有考慮在其中。其實已經有大神給咱們寫好的react-loadable,使用起來至關方便,再次我也不在贅述了。

相關文章
相關標籤/搜索