Web應用一個重要的優點就在於能夠只加載咱們想要的功能,而沒必要每次打開都把整個系統載入react
那麼,在React裏咱們怎樣實現當用到咱們需求的功能時再請求對應的組件,而不是一次性的請求所有代碼呢?webpack
新版的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 組件也是模塊,所以可使用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也很是簡單,由於已經把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> ) } }