分享:使用 webpack 的 require.context 实现路由“去中心化”管理

来源:互联网 发布:php redis连接池配置 编辑:程序博客网 时间:2024/06/08 04:47

阅读须知:示例代码以 react-router V3 为例。其他路由同样适用,如:vue-router。同样其他的功能模块也可以用该思路进行相应的去中心化管理改造。

本文示例代码

一个项目中路由的变化过程

当你在开发一个大型单页面应用的时候,项目之初一般做法是所有的路由规则都维护在一个route.js的文件里。

// rootRoute.jsconst rootRoute = {    childRoutes: [        {            path: '/',            component: AppLayout,            childRoutes: [                {                    path: 'shop', // 购买详情页                    component: Shop                },                {                    path: 'order', // 订单页                    component: Order                }                // ...                // 少量其他路由                // ...            ]        }    ]};

随着业务代码的增长路由很快会变成:

// rootRoute.jsconst 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 提供的思路,对路由按业务模块进行拆分。

// rootRoute.jsconst 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,我们可以通过正则匹配引入相应的文件模块。

require.context(directory, useSubdirectories, regExp)

require.context 有三个参数:

  • directory:说明需要检索的目录
  • useSubdirectories:是否检索子目录
  • regExp: 匹配文件的正则表达式

使用 require.context 改造后的 rootRoute.js 文件

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 里。
查看示例代码

其他应用场景

这个思路可应用于其他想要实现"去中心化"管理的功能模块。

  • 模块化管理 reducer

转载出处: https://github.com/wuchangming/blog/blob/master/docs/webpack/require-context-usage.md