react-router之代码分离
概念
无需用户下载整个应用之后才能访问访问它。即边访问边下载。因此我们设计一个组件<Bundle>
当用户导航到它是来动态加载组件。
import loadSomething from 'bundle-loader?lazy!./Something'
<Bundle load={loadSomething}>
{(mod) => (
// do something w/ the module
)}
</Bundle>
如果model是一个component:
<Bundle load={loadSomething}>
{(Comp) => (Comp
? <Comp/>
: <Loading/>
)}
</Bundle>
这个组件拥有一个load属性(即webpack的 bundle loader)。当组件挂载或者得到一个新的load属性,它将调用load属性,然后放置组件的returned value 到state中,最后在组件的render中回掉该model。源码:
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。这样,我们就可以向用户展示一个等待的动画,表明我们正在等待什么东西。
Why bundle loader, and not import()?
TC39 最近提出的官方的动态导入是import(),我们可以调整我们的Bundle来使用它:
<Bundle load={() => import('./something')}>
{(mod) => ()}
</Bundle>
bundle loader的最大好处是它第二次同步回调。这样可以在用户每次访问一个代码分离的页面时防止加载页面而造成的页面闪烁。
忽视你import的方式,思想时一样的:code splitting 即,当组件呈现时用来处理该组件加载的组件。现在你要做的就是在你想要动态加载代码的地方使用<Bundle>
。
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的其余部分去处理它
ReactDOM.render(<App/>, preloadTheRestOfTheApp)
作者:禅楼望月
出处:http://www.cnblogs.com/yaoyinglong
如果,您认为阅读这篇博文让您有些收获,不妨点击一下右下角的【推荐】
如果,您希望这篇博文也能帮助到其他人,不妨点击一下右边的【分享到…】
如果,您希望更容易地发现我的新博客,不妨点击一下左下角的【关注我】
如果,您对我的博客内容感兴趣,请继续关注我的后续博客,我是【禅楼望月】
本文版权归作者和博客园共有,欢迎转载,但请注明出处,且在文章页面明显位置给出原文连接。