React組件懶加載

React組件懶加載

Web應用一個重要的優點就在於能夠只加載咱們想要的功能,而沒必要每次打開都把整個系統載入react

那麼,在React裏咱們怎樣實現當用到咱們需求的功能時再請求對應的組件,而不是一次性的請求所有代碼呢?webpack

bundle-loader

新版的React建議咱們使用bundle-loader進行代碼的分離,下面咱們看下它的用法:git

// 當你用到這個函數時,這個chunk纔會被請求
var waitForChunk = require("bundle-loader!./file.js");

//  當請求的chunk加載完成纔會執行傳入的回調函數,並將請求的模塊做爲參數傳入回調函數
waitForChunk(function(file) {
    // 接收到懶加載模塊,相似於下面代碼
    // var file = require("./file.js");
});

這個插件使用很是簡單,只是對require.ensure的封裝,使用起來相似於AMD的方式,
只需在回調函數裏接收到懶加載的模塊便可。github

結合React

React 組件也是模塊,所以可使用bundle-loader進行代碼分離,只是須要在合適的地方請求調用便可。web

怎樣知道什麼時候須要請求這個組件呢?社區建議的是先加載一個bundle容器組件(這個bundle容器組件自己很是小),當這個容器組件被渲染到dom時則可認爲咱們須要請求對應的懶加載組件了。app

咱們能夠爲全部的懶加載組件封裝一個通用的容器組件:
(這裏也有已經封裝好的:react-lazy-bundle,直接安裝便可)dom

import React, { Component } from "react";

class Bundle extends Component {
  state = {
    // 由於module被佔用了,咱們用mod定義變量
    mod: null
  };

  componentWillMount() {
    this.load(this.props);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.load !== this.props.load) {
      this.load(nextProps);
    }
  }

  load(props) {
    this.setState({
      mod: null
    });
    props.load(mod => {
      this.setState({
        // 爲了兼容es module 和 AMD module
        mod: mod.default ? mod.default : mod
      });
    });
  }

  render() {
    //若加載完成則渲染對應懶加載的組件,反之加載beforeLoad傳入的組件
    return this.state.mod
      ? <this.state.mod {...this.props} />
      : <this.props.beforeLoad {...this.props} />;
  }
}

export default Bundle;

如上封裝,使用時咱們只需以下便可:函數

import React, { Component } from "react";
import Bundle from "./Bundle";

import Test from "bundle-loader?lazy&name=[name]!./test";

const BeforeLoadComponent = props =>
  <div>
    before load {props.name}
  </div>;

class HomePage extends Component {
  render() {
    return (
      <div>
        <Bundle name="flypie" load={Test} beforeLoad={BeforeLoadComponent} />
      </div>
    );
  }
}

export default HomePage;

怎麼樣,是否是特別簡單ui

結合React Router

結合React Router也很是簡單,由於已經把Bundle做爲Route的component參數了,
因此要再封裝一層,把load和beforeLoad預先傳入便可。this

import Bundle from "./Bundle";
import About from "bundle-loader?lazy&name=[name]!./About";

const AboutWrapper = props => <Bundle load={About} {...props}/>;

class App extends Component {

  render() {
    return (
      <div>
        <h1>Welcome!</h1>
        <Route path="/about" component={AboutWrapper}/>
      </div>
    )
  }
}
相關文章
相關標籤/搜索