Taro 小程序路由全自动配置
发表时间:2021-1-5
发布人:葵宇科技
浏览次数:210
使用过 Umi 框架的人一定会对它的约定式路由印象深刻。在约定式路由模式下,pages 目录下新建文件,其他页面即可直接书写链接进行跳转。
Taro 框架中自带了路由功能,但是每新建一个页面文件后,需要在 app.config.ts 文件中配置页面地址,在进行页面跳转时,还需要带上长长的一串链接,书写麻烦的同时还容易出错。
navigateTo({
url: `/package-appointment/pages/manage-appointments/index?roomId=${roomId}&appointmentId=${appointmentId}&scriptId=${scriptId}`
})
复制代码
将页面地址维护到一个映射表中,方便管理和使用。
navigateTo({
url: `${URLs.ManageAppointment}?roomId=${roomId}&appointmentId=${appointmentId}&scriptId=${scriptId}`
})
复制代码
但是又带来的新的问题,开发一个页面,不仅要维护 app.config.ts 还要维护映射表文件。且参数又长又不美观。
如何解决这些问题呢?
经过我不断摸索,可以做到新建页面文件后,0配置,其他页面直接调用类似下面的API,即可进行跳转
routerService.toManageAppointments({ roomId, appointmentId, scriptId })
复制代码
下图演示了,删除分包页面后,自动更新 app.config.ts
实现原理很简单:1.监听页面文件创建。2.执行脚本修改和生成代码。
监听页面文件/文件夹创建说到监听,我们首先会想到 webpack -watch 模式。但要注意的是,webpack 只监听代码依赖树中的文件,即新建的文件或文件夹是不会被 webpack 监听的。那如何实现监听页面文件的创建呢?Node 有 watch API 可以实现这一点,但在各个平台可能存在各种各样的问题,因而我使用了 chokidar 去监听文件创建。
工具是有了,但怎么整合到项目中呢?总不能打开两个控制台,一个跑项目,一个跑文件监听吧。webpack-plugin-chokidar插件可以解决问题,通过 taro 的 webpackChain 配置,可以很容易监听文件/文件夹修改。
插件监听配置实例如下
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
命令,读取插件配置文件夹的配置供插件使用。我们的功能需要通过插件实现,安装该工具后进行下列配置。
1、在根目录新建 generated 配置文件 .generatedrc.ts
2、注册插件
import { GeneratedrcConfig } from 'generated'
const generatedrc: GeneratedrcConfig = {
configDir: './gconfig', // generated 插件配置目录
plugins: [
'generated-plugin-taro-router-service' // 注册插件
],
}
export default generatedrc
复制代码
generated-plugin-taro-router-service
在这个插件中,实现了修改代码和生成routerService
文件。
需要进行下列配置
1、在根目录新建 gconfig 文件夹,文件夹下新建 router.ts 配置文件.
2、写入配置
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 进行脚本调用在文件监听的回调函数中,利用 shelljs 执行 generated
命令即可。
本文提到的几个仓库如下:
- ts-morph 修改、生成 typescript 代码
- chokidar 监听文件变动
- webpack-plugin-chokidar 将 chokidar 整合到 webpack 使用,需在 webpack dev 模式下使用
- generated 代码生成管理工具
- generated-plugin-taro-router-service 修改代码脚本