詳解webpack + react + react-router 如何實(shí)現(xiàn)懶加載
在 Webpack 1 中主要是由bundle-loader進(jìn)行懶加載,而 Webpack 2 中引入了類似于 SystemJS 的System.import語法,首先我們對于System.import的執(zhí)行流程進(jìn)行簡單闡述:
- Webpack 會在編譯過程中掃描代碼庫時(shí)將發(fā)現(xiàn)的System.import調(diào)用引入的文件及其相關(guān)依賴進(jìn)行單獨(dú)打包,注意,Webpack 會保證這些獨(dú)立模塊及其依賴不會與主應(yīng)用的包體相沖突。
- 當(dāng)我們訪問到這些獨(dú)立打包的組件模塊時(shí),Webpack 會發(fā)起 JSONP 請求來抓取相關(guān)的包體。
- System.import 同樣也是 Promise,在請求完成之后System.import會將抓取到的模塊作為參數(shù)傳入then中的回調(diào)函數(shù)。
- 如果我們重復(fù)訪問已經(jīng)加載完畢的模塊,Webpack 不會重復(fù)執(zhí)行抓取與解析的過程。
而 React Router 路由的懶加載實(shí)際上分為動(dòng)態(tài)路由與與懶加載兩步,典型的所謂動(dòng)態(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> ) }
這是一個(gè)正常打包的路由寫法, 如果需要分割代碼, 我們需要改造下路由, 借助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> ) }
這樣看來代碼有點(diǎn)累, 我們稍微改造下
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 實(shí)現(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以create-react-app為基礎(chǔ)創(chuàng)建項(xiàng)目
這篇文章主要介紹了react以create-react-app為基礎(chǔ)創(chuàng)建項(xiàng)目,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03ReactNative?狀態(tài)管理redux使用詳解
這篇文章主要介紹了ReactNative?狀態(tài)管理redux使用詳解2023-03-03學(xué)習(xí)ahooks useRequest并實(shí)現(xiàn)手寫
這篇文章主要為大家介紹了學(xué)習(xí)ahooks useRequest并實(shí)現(xiàn)手寫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03react native基于FlatList下拉刷新上拉加載實(shí)現(xiàn)代碼示例
這篇文章主要介紹了react native基于FlatList下拉刷新上拉加載實(shí)現(xiàn)代碼示例2018-09-09React-router?v6在Class組件和非組件代碼中的正確使用
這篇文章主要介紹了React-router?v6在Class組件和非組件代碼中的正確使用方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03React Native使用百度Echarts顯示圖表的示例代碼
本篇文章主要介紹了React Native使用百度Echarts顯示圖表的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-11-11