詳解webpack + react + react-router 如何實現(xiàn)懶加載
在 Webpack 1 中主要是由bundle-loader進(jìn)行懶加載,而 Webpack 2 中引入了類似于 SystemJS 的System.import語法,首先我們對于System.import的執(zhí)行流程進(jìn)行簡單闡述:
- Webpack 會在編譯過程中掃描代碼庫時將發(fā)現(xiàn)的System.import調(diào)用引入的文件及其相關(guān)依賴進(jìn)行單獨打包,注意,Webpack 會保證這些獨立模塊及其依賴不會與主應(yīng)用的包體相沖突。
- 當(dāng)我們訪問到這些獨立打包的組件模塊時,Webpack 會發(fā)起 JSONP 請求來抓取相關(guān)的包體。
- System.import 同樣也是 Promise,在請求完成之后System.import會將抓取到的模塊作為參數(shù)傳入then中的回調(diào)函數(shù)。
- 如果我們重復(fù)訪問已經(jīng)加載完畢的模塊,Webpack 不會重復(fù)執(zhí)行抓取與解析的過程。
而 React Router 路由的懶加載實際上分為動態(tài)路由與與懶加載兩步,典型的所謂動態(tài)路由配置如下:
/**
* <Route path="/" component={Core}>
* <IndexRoute component={Home}/>
* <Route path="about" component={About}/>
* <Route path="users" component={Users}>
* <Route path="*" component={Home}/>
* </Route>
*/
export default {
path: '/',
component: Core,
indexRoute: {
getComponent(location, cb) {
...
},
},
childRoutes: [
{
path: 'about',
getComponent(location, cb) {
...
},
},
{
path: 'users',
getComponent(location, cb) {
...
},
},
{
path: '*',
getComponent(location, cb) {
...
},
},
],
};
正常打包
import IndexPage from './views/app.jsx'
import AboutPage from './views/about.jsx'
export default function({history}) {
return (
<Router history={history}>
<Route path="/" component={IndexPage} />
<Route path="/about" component={AboutPage} />
</Router>
)
}
這是一個正常打包的路由寫法, 如果需要分割代碼, 我們需要改造下路由, 借助getComponent和require.ensure
webpack 代碼分割
export default function({history}) {
return (
<Router history={history}>
<Route path="/" getComponent={(location, callback) => {
require.ensure([], function(require) {
callback(null, require('./HomePage.jsx'))
})
}} />
<Route path="/about" getComponent={(location, callback) => {
require.ensure([], function(require) {
callback(null, require('./AboutPage.jsx'))
})
}} />
</Router>
)
}
這樣看來代碼有點累, 我們稍微改造下
const home = (location, callback) => {
require.ensure([], require => {
callback(null, require('./HomePage.jsx'))
}, 'home')
}
const about = (location, callback) => {
require.ensure([], require => {
callback(null, require('./AboutPage.jsx'))
}, 'about')
}
export default function({history}) {
return (
<Router history={history}>
<Route path="/" getComponent={home}></Route>
<Route path="/about" getComponent={about}></Route>
</Router>
)
}
這樣看起來是不是簡潔了很多
注意: 由于webpack的原因, 如果直接require('./AboutPage.jsx')不能正常加載, 請嘗試require('./AboutPage.jsx').default
webpack2 代碼分割
上面的代碼看起來好像都是webpack1的寫法, 那么webpack2呢?
webpac2就需要借助System.import了
export default function({history}) {
return (
<Router history={history}>
<Route path="/" getComponent={(location, callback) => {
System.import('./HomePage.jsx').then(component => {
callback(null, component.default || component)
})
}} />
<Route path="/about" getComponent={(location, callback) => {
System.import('./AboutPage.jsx').then(component => {
callback(null, component.default || component)
})
}} />
</Router>
)
}
我們一樣可以把上面的代碼優(yōu)化一下
const home = (location, callback) => {
System.import('./HomePage.jsx').then(component => {
callback(null, component.default || component)
})
}
const about = (location, callback) => {
System.import('./AboutPage.jsx').then(component => {
callback(null, component.default || component)
})
}
export default ({ history }) => {
return (
<Router history={history}>
<Route name="home" path="/" getComponent={home} />
<Route name="about" path="/about" getComponent={about} />
</Router>
)
}
webpack2 + dva 實現(xiàn)路由和 models 懶加載
const routerThen = (app, callback, [component, model]) => {
app.model(model.default || model)
callback(null, component.default || component)
}
export default ({ history, app }) => {
return (
<Router history={history}>
<Route name="home" path="/" getComponent={(location, callback) => {
Promise.all([
System.import('./views/app.jsx'),
System.import('./models/topics')
]).then(routerThen.bind(null, app, callback))
}} />
<Route name="article" path="/article/:id" getComponent={(location, callback) => {
Promise.all([
System.import('./views/article.jsx'),
System.import('./models/topic')
]).then(routerThen.bind(null, app, callback))
}} />
</Router>
)
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
React+valtio響應(yīng)式狀態(tài)管理
Valtio是一個很輕量級的響應(yīng)式狀態(tài)管理庫,使用外部狀態(tài)代理去驅(qū)動React視圖來更新,本文主要介紹了React+valtio響應(yīng)式狀態(tài)管理,感興趣的可以了解一下2023-12-12
React前端開發(fā)createElement源碼解讀
這篇文章主要為大家介紹了React前端開發(fā)createElement源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
React中useRef與useState的使用與區(qū)別
本文介紹了React中兩個常用的鉤子useRef和useState,包含比較它們的功能并提供示例來說明它們的用法,具有一定的參考價值,感興趣的可以了解一下2024-11-11
react實現(xiàn)antd線上主題動態(tài)切換功能
這篇文章主要介紹了react實現(xiàn)antd線上主題動態(tài)切換功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-08-08

