Taro 小程序路由全自動配置

前言

使用過 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.tsnpm

正文

實現原理很簡單: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.jsonapp.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,不想安裝這幾個包的,能夠參考modifyAppConfiggenerateRouterService 代碼實現,改一改以後,編譯成 js 代碼,直接在監聽文件變動的回調函數中使用便可。

generated

這是一個代碼生成管理工具。代碼很簡單,它註冊了一個 generated 命令,讀取插件配置文件夾的配置供插件使用。咱們的功能須要經過插件實現,安裝該工具後進行下列配置。

一、在根目錄新建 generated 配置文件 .generatedrc.ts

二、註冊插件

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文件。

須要進行下列配置

一、在根目錄新建 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 進行腳本調用

在文件監聽的回調函數中,利用 shelljs 執行 generated 命令便可。

其餘

本文提到的幾個倉庫以下:

相關文章
相關標籤/搜索