react-router實現按需加載

本文使用的 react-router 版本爲 2.8.1react

React Router本身就有一套按需加載解決方案,將代碼拆分紅多個小包,在瀏覽過程當中實現按需加載;webpack

如過你的項目搭配了webpack打包工具,那麼須要在webpack.config.jsoutput內加上chunkFilenameweb

output: {
    path: path.join(__dirname, '/../dist/assets'),
    filename: 'app.js',
    publicPath: defaultSettings.publicPath,
    // 添加 chunkFilename
    chunkFilename: '[name].[chunkhash:5].chunk.js',
},
複製代碼

name是代碼裏建立chunk指定的名字,若是代碼中沒有指定,則webpack會默認分配id號碼做爲name; chunkhash是文件的hash碼,由於hash碼比較長,因此這裏只取前五位。bash

咱們須要讓路由動態加載組件,須要將 component 換成 getComponent。首先將路由拆出來,建立一個根路由 rootRoute:react-router

const rootRoute = {
  path: '/',
  indexRoute: {
    getComponent(nextState, cb) {
      require.ensure([], (require) => {
        cb(null, require('components/layer/HomePage'))
      }, 'HomePage')
    },
  },
  getComponent(nextState, cb) {
    require.ensure([], (require) => {
      cb(null, require('components/Main'))
    }, 'Main')
  },
  childRoutes: [
    require('./routes/baidu'),
    require('./routes/404'),
    require('./routes/redirect')
  ]
}

ReactDOM.render(
  (
    <Router
      history={browserHistory}
      routes={rootRoute}
      />
  ), document.getElementById('root')
);
複製代碼

這裏有四個屬性:app

path 不用多說,匹配路由;異步

getComponent 對應於之前的 component 屬性,可是這個方法是異步的,也就是當路由匹配時,纔會調用這個方法。函數

這裏面有個 require.ensure 方法工具

require.ensure(dependencies, callback, chunkName)
複製代碼

這是 webpack 提供的方法,這也是按需加載的核心方法。第一個參數是依賴,第二個是回調函數,第三個就是上面提到的 chunkName,用來指定這個 chunk file 的 name。ui

indexRoute 用來設置主頁。(單獨抽離主頁) 注意這裏的 indexRoute 寫法, 這是個對象,在對象裏面使用 getComponent。

childRoutes 子路由 這裏面放置的就是子路由的配置,對應於之前的子路由們。咱們將之前的 /baidu、/404 和 * 都拆了出來,接下來將分別爲他們建立路由配置。

路由控制 上面的childRoutes 裏面,咱們 require 了三個子路由,在目錄下建立 routes 目錄,將這三個路由放置進去。

routes/
├── 404
│   └── index.js
├── baidu
│   ├── index.js
│   └── routes
│       ├── frequency
│       │   └── index.js
│       └── result
│           └── index.js
└── redirect
    └── index.js
複製代碼

和 rootRoute 相似,裏面的每一個 index.js 都是一個路由對象: /404/index.js

module.exports = {
  path: '404',

  getComponent(nextState, cb) {
    require.ensure([], (require) => {
      cb(null, require('components/layer/NotFoundPage'))
    }, 'NotFoundPage')
  }
}
複製代碼

/baidu/index.js

module.exports = {
  path: 'baidu',

  getChildRoutes(partialNextState, cb) {
    require.ensure([], (require) => {
      cb(null, [
        require('./routes/result'),
        require('./routes/frequency')
      ])
    })
  },

  getComponent(nextState, cb) {
    require.ensure([], (require) => {
      cb(null, require('components/layer/BaiduPage'))
    }, 'BaiduPage')
  }
}
複製代碼

/baidu/routes/frequency/index.js

module.exports = {
  path: 'frequency',
  getComponent(nextState, cb) {
    require.ensure([], (require) => {
      cb(null, require('components/layer/BaiduFrequencyPage'))
    }, 'BaiduFrequencyPage')
  }
}
複製代碼

等················

下面來講一下設置Redirect

咱們須要把這個重定向的路由單獨拆出來,也就是 * 這個路由,咱們上面已經爲他建立了一個 redirect 目錄。這裏使用到 onEnter 方法,而後在這個方法裏改變路由狀態,調到另外的路由,實現 redirect :

/redirect/index.js官方例子

module.exports = {
  path: '*',
  onEnter: (_, replaceState) => replaceState(null, "/404")
}
複製代碼
相關文章
相關標籤/搜索