一个项目中路由的变化过程
当你在开发一个大型单页面应用的时候,项目之初一般做法是所有的路由规则都维护在一个route.js的文件里。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| const rootRoute = { childRoutes: [ { path: '/', component: AppLayout, childRoutes: [ { path: 'shop', component: Shop }, { path: 'order', component: Order } ] } ] };
|
随着业务代码的增长路由很快会变成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| const rootRoute = { childRoutes: [ { path: '/', component: AppLayout, childRoutes: [ { path: 'shop', component: ShopLayout, childRoutes: [ { path: 'foodDetail', component: FoodDetail }, { path: 'shoesDetail', component: ShoesDetail } ] }, { path: 'order', component: Order, childRoutes: [ { path: 'remark', component: Remark }, { path: 'invoice', component: Invoice }, { path: 'payment', component: Payment }, { path: 'userValidation', component: UserValidation }, { path: 'chooseAddress', component: ChooseAddress, childRoutes: [ { path: 'addAddress', component: AddAddress, childRoutes: [ { path: 'searchAddress', component: SearchAddress } ] } ] } ] } ] } ] };
|
当路由变的越来越大,大到已经难以维护时。我们按照react-router提供的思路,对路由按业务模块进行拆分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const rootRoute = { childRoutes: [ { path: '/', component: AppLayout, childRoutes: [ require('./modules/shop/route'), require('./modules/order/route'), require('./modules/login/route'), require('./modules/service/route'), ] } ] };
|
按该方式拆分后,每个业务模块维护自身的路由配置。新增业务模块路由,只需要在总的rootRoute中引入该业务模块的路由即可(也就是加一行代码)。这个方案看来是已经接近完美了。但如果想达到连一行代码都不用加?实现彻彻底底的去中心化管理
require.context是什么?
想要彻彻底底的实现去中心化管理我们需要使用到require.context
webpack官方文档的介绍require.context
简单说就是:有了require.context,我们可以通过正则匹配引入相应的文件模块。
1
| require.context(directory, useSubdirectories, regExp)
|
require.context有三个参数:
- directory:说明需要检索的目录
- useSubdirectories:是否检索子目录
- regExp: 匹配文件的正则表达式
使用require.context改造后的rootRoute.js文件
1 2 3 4 5 6 7 8 9 10 11
| const rootRoute = { childRoutes: [ { path: '/', component: AppLayout, childRoutes: (r => { return r.keys().map(key => r(key)); })(require.context('./', true, /^\.\/modules\/((?!\/)[\s\S])+\/route\.js$/)) } ] };
|
优化后,新增一个业务模块,只要业务模块route文件遵循统一的目录结构。业务模块route就能被自动关联到rootRoute里。
查看示例代码
其他应用场景
这个思路可应用于其他想要实现”去中心化”管理的功能模块。