使用過 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 修改代碼腳本