react-router之代码分离

概念

无需用户下载整个应用以后才能访问访问它。即边访问边下载。所以咱们设计一个组件<Bundle>当用户导航到它是来动态加载组件。javascript

import loadSomething from 'bundle-loader?lazy!./Something'

<Bundle load={loadSomething}>
  {(mod) => (
    // do something w/ the module
  )}
</Bundle> 

若是model是一个component:html

<Bundle load={loadSomething}>
  {(Comp) => (Comp
    ? <Comp/>
    : <Loading/>
  )}
</Bundle>

这个组件拥有一个load属性(即webpack的 bundle loader)。当组件挂载或者获得一个新的load属性,它将调用load属性,而后放置组件的returned valuestate中,最后在组件的render中回掉该model。源码:java

import React, { Component } from 'react'

class Bundle extends Component {
  state = {
    // short for "module" but that's a keyword in js, so "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({
        // handle both es imports and cjs
        mod: mod.default ? mod.default : mod
      })
    })
  }

  render() {
    return this.state.mod ? this.props.children(this.state.mod) : null
  }
}

export default Bundle

上面render中代表,在model获取以前,render将调用 null state.mod。这样,咱们就能够向用户展现一个等待的动画,代表咱们正在等待什么东西。webpack

Why bundle loader, and not import()?

TC39 最近提出的官方的动态导入是import(),咱们能够调整咱们的Bundle来使用它:web

<Bundle load={() => import('./something')}>
  {(mod) => ()}
</Bundle> 

bundle loader的最大好处是它第二次同步回调。这样能够在用户每次访问一个代码分离的页面时防止加载页面而形成的页面闪烁。typescript

忽视你import的方式,思想时同样的:code splitting 即,当组件呈现时用来处理该组件加载的组件。如今你要作的就是在你想要动态加载代码的地方使用<Bundle>app

Loading after rendering is complete

Bundle component一样也有利于预在后台预加载app的其他部分。动画

import loadAbout from 'bundle-loader?lazy!./loadAbout'
import loadDashboard from 'bundle-loader?lazy!./loadDashboard'

// components load their module for initial visit
const About = (props) => (
  <Bundle load={loadAbout}>
    {(About) => <About {...props}/>}
  </Bundle>
)

const Dashboard = (props) => (
  <Bundle load={loadDashboard}>
    {(Dashboard) => <Dashboard {...props}/>}
  </Bundle>
)

class App extends React.Component {
  componentDidMount() {
    // preloads the rest
    loadAbout(() => {})
    loadDashboard(() => {})
  }

  render() {
    return (
      <div>
        <h1>Welcome!</h1>
        <Route path="/about" component={About}/>
        <Route path="/dashboard" component={Dashboard}/>
      </div>
    )
  }
}

何时,多少个你的app要被加载,由你决定。不须要绑定特殊的route。也许你仅仅在用户不活跃的时候,也或许仅仅在用户访问一个route时,或许你想在初始render以后预加载app的其他部分去处理它ui

ReactDOM.render(<App/>, preloadTheRestOfTheApp)
相关文章
相关标签/搜索