使用过 Umi 框架的人必定会对它的约定式路由印象深入。在约定式路由模式下,pages 目录下新建文件,其余页面便可直接书写连接进行跳转。webpack
Taro 框架中自带了路由功能,可是每新建一个页面文件后,须要在 app.config.ts 文件中配置页面地址,在进行页面跳转时,还须要带上长长的一串连接,书写麻烦的同时还容易出错。git
navigateTo({
url: `/package-appointment/pages/manage-appointments/index?roomId=${roomId}&appointmentId=${appointmentId}&scriptId=${scriptId}`
})
复制代码
将页面地址维护到一个映射表中,方便管理和使用。github
navigateTo({
url: `${URLs.ManageAppointment}?roomId=${roomId}&appointmentId=${appointmentId}&scriptId=${scriptId}`
})
复制代码
可是又带来的新的问题,开发一个页面,不只要维护 app.config.ts 还要维护映射表文件。且参数又长又不美观。web
如何解决这些问题呢?typescript
通过我不断摸索,能够作到新建页面文件后,0配置,其余页面直接调用相似下面的API,便可进行跳转shell
routerService.toManageAppointments({ roomId, appointmentId, scriptId })
复制代码
下图演示了,删除分包页面后,自动更新 app.config.ts
npm
实现原理很简单:1.监听页面文件建立。2.执行脚本修改和生成代码。json
说到监听,咱们首先会想到 webpack -watch 模式。但要注意的是,webpack 只监听代码依赖树中的文件,即新建的文件或文件夹是不会被 webpack 监听的。那如何实现监听页面文件的建立呢?Node 有 watch API 能够实现这一点,但在各个平台可能存在各类各样的问题,于是我使用了 chokidar 去监听文件建立。babel
工具是有了,但怎么整合到项目中呢?总不能打开两个控制台,一个跑项目,一个跑文件监听吧。webpack-plugin-chokidar插件能够解决问题,经过 taro 的 webpackChain 配置,能够很容易监听文件/文件夹修改。markdown
插件监听配置实例以下
const basePath = path.resolve(__dirname, '../src');
...
new WebPackPluginChokidar({
chokidarConfigList: [
{
file: basePath + '/**/pages/**/index.tsx', // 监听路径(支持主包和分包)
opt: { persistent: true, ignoreInitial: true }, // 监听配置选项( 配置项参考chokidar)
actions: {
on: {
add: ({ compiler, compilation, watcher }, path, ...rest) => { // 监听文件建立
console.log(`File ${path} has been added`);
},
},
},
},
],
});
复制代码
在上面代码中,只须要在 add
回调函数中,调用修改代码脚本便可。
这一步中,须要修改 project.config.json
和app.config.ts
,和生成 routerService.ts
文件。project.config.json
文件很好处理,直接在脚本中经过 require
引入,当作一个 JS 对象操做,最后经过 Node fs API 写入便可。
咱们修改代码最经常使用的是直接 fs.readFile
读文件,字符串匹配更换文本,这样操做虽然简单快捷,但精度低,且不够优雅。
Babel玩的熟的,会使用 babel 解析代码成 ast,修改 ast, 最后 generate 代码,再写入文件。
ts-morph是一个新增/修改 typescript 代码的库,相比 babel 修改 ts 代码, 更简单,更易使用。
我使用了 ts-morph 修改 app.config.ts 和生成 routerService.ts。
下面的配置,是咱们项目目前在使用的部分配置,嫌麻烦的,能够直接到这里下载 demo,不想安装这几个包的,能够参考modifyAppConfig,generateRouterService 代码实现,改一改以后,编译成 js 代码,直接在监听文件变动的回调函数中使用便可。
这是一个代码生成管理工具。代码很简单,它注册了一个 generated
命令,读取插件配置文件夹的配置供插件使用。咱们的功能须要经过插件实现,安装该工具后进行下列配置。
一、在根目录新建 generated 配置文件 .generatedrc.ts
二、注册插件
import { GeneratedrcConfig } from 'generated'
const generatedrc: GeneratedrcConfig = {
configDir: './gconfig', // generated 插件配置目录
plugins: [
'generated-plugin-taro-router-service' // 注册插件
],
}
export default generatedrc
复制代码
在这个插件中,实现了修改代码和生成routerService
文件。
须要进行下列配置
一、在根目录新建 gconfig 文件夹,文件夹下新建 router.ts 配置文件.
二、写入配置
import { Config } from 'generated-plugin-taro-router-service'
const basePath = process.cwd()
export const taroRouter: Config = {
// 源码目录
pageDir: basePath + '/src',
// app.config 路径
appConfigPath: basePath + '/src/app.config.ts',
// project.config.json 路径
projectConfigPath: basePath + '/project.config.json',
// 输出文件名
outputFileName: 'routerService',
/** * 导入组件 * * 输出的文件将导入方法 * import { customNavigateTo } from '@/business/app' */
navigateFnName: 'customNavigateTo', // 导入方法名
navigateSpecifier: '@/business/app', // 方法导入标识符
/** * 格式化文件名 * 页面文件名可能会出现相似 edit-name 的写法,这种 name 没法做为类属性,因此须要 formatter 函数格式化 */
formatter(name) {
return (name.split('-') || []).reduce((t, c) => t + upFirst(c), '')
}
}
复制代码
工具内部没有直接使用taro 原生的 navigateTo 方法,而是须要手动配置方法。一是由于 taro 导出的路由 API 并很差用,二是 API 封装在内部,自定义程度不够高。
在文件监听的回调函数中,利用 shelljs 执行 generated
命令便可。
本文提到的几个仓库以下:
- ts-morph 修改、生成 typescript 代码
- chokidar 监听文件变更
- webpack-plugin-chokidar 将 chokidar 整合到 webpack 使用,需在 webpack dev 模式下使用
- generated 代码生成管理工具
- generated-plugin-taro-router-service 修改代码脚本