preface

Anyone who has used the Umi framework will be impressed by its contract routing. In the reduced-form routing mode, a new file is created in the Pages directory, and other pages can be directly linked to jump.

The Taro framework has its own routing function. However, you need to configure the page address in the app.config.ts file every time you create a new page file.

navigateTo({
  url: `/package-appointment/pages/manage-appointments/index? roomId=${roomId}&appointmentId=${appointmentId}&scriptId=${scriptId}`
})
Copy the code

Maintain the page address in a mapping table for easy management and use.

navigateTo({
  url: `${URLs.ManageAppointment}? roomId=${roomId}&appointmentId=${appointmentId}&scriptId=${scriptId}`
})
Copy the code

However, it brings new problems. Developing a page not only maintains app.config.ts but also maintains mapping table files. And the parameters are long and unattractive.

How to solve these problems?

After my constant exploration, I can do 0 configuration after the new page file, and other pages can directly call the API similar to the following, and then jump

routerService.toManageAppointments({ roomId, appointmentId, scriptId })
Copy the code

The following figure illustrates how app.config.ts is automatically updated after the subcontracting page is deleted

The body of the

The implementation principle is simple: 1. Listen for page file creation. 2. Modify the script and generate the code.

Listen for page file/folder creation

When it comes to listening, the first thing that comes to mind is the Webpack-Watch mode. Note, however, that WebPack only listens for files in the code dependency tree, i.e. new files or folders are not listened for by WebPack. So how do you create a listener page file? Node has the Watch API to do this, but there can be various issues across platforms, so I used Chokidar to listen for file creation.

The tools are there, but how are they integrated into the project? You can’t open two consoles, one for project and one for file listening. The webpack-plugin-Chokidar plugin solves this problem by making it easy to listen for file/folder changes through Taro’s webpackChain configuration.

An example of plug-in listening configuration is as follows

const basePath = path.resolve(__dirname, '.. /src'); .new WebPackPluginChokidar({
  chokidarConfigList: [{file:  basePath + '/**/pages/**/index.tsx'.// Listen to the path (support main package and subpackage)
      opt: { persistent: true.ignoreInitial: true },	// Listen for configuration options (see Chokidar for configuration items)
      actions: {
        on: {
          add: ({ compiler, compilation, watcher }, path, ... rest) = > {	// Listen for file creation
            console.log(`File ${path} has been added`); },},},},],});Copy the code

In the above code, all you need to do is call the modify code script in the add callback.

Code modification and generation

In this step, you need to modify project.config.json and app.config.ts and generate the RouterService. ts file. The project.config.json file is easy to handle, imported directly from the script via require, manipulated as a JS object, and then written via the Node FS API.

The most common way we modify code is to read fs.readfile directly, and replace text with string matching. This operation is simple and quick, but it is not precise and elegant.

Babel is familiar with parsing code into an AST, modifying the AST, and finally generating code to write to a file.

Ts-morph is a library for adding/modifying typescript code that is much simpler and easier to use than Babel for modifying TS code.

I used TS-morph to modify app.config.ts and generate RouterService.ts.

The following configuration is part of the configuration that our project is currently using. If you don’t want to bother, you can download demo directly here. If you don’t want to install these packages, you can refer to modifyAppConfig and generateRouterService code for implementation. Use it directly in the callback function that listens for file changes.

generated

This is a code generation management tool. The code is very simple, it registers a generated command, read the plug-in configuration folder configuration for the plug-in to use. Our functionality needs to be implemented through a plug-in. After installing the tool, perform the following configuration.

1. Create the generated configuration file.generateDRC

2. Register the plugin

import { GeneratedrcConfig } from 'generated'

const generatedrc: GeneratedrcConfig = {
  configDir: './gconfig'.// Directory for configuring the generated plug-in
  plugins: [
    'generated-plugin-taro-router-service'  // Register the plug-in],}export default generatedrc
Copy the code

generated-plugin-taro-router-service

In this plug-in, you modify the code and generate the routerService file.

The following configuration is required

1. Create the gconfig folder in the root directory and create the router.ts configuration file in the folder.

2. Write the configuration

import { Config } from 'generated-plugin-taro-router-service'

const basePath = process.cwd()

export const taroRouter: Config = {
  // Source directory
  pageDir: basePath + '/src'./ / app. Config path
  appConfigPath: basePath + '/src/app.config.ts'./ / project. Config. Json path
  projectConfigPath: basePath + '/project.config.json'.// Output the file name
  outputFileName: 'routerService'./** * Import component ** output file will import method * import {customNavigateTo} from '@/business/app' */
  navigateFnName: 'customNavigateTo'.// Import method name
  navigateSpecifier: '@/business/app'.// The method imports the identifier
  
  Page file names can be written like edit-name. This name cannot be used as a class attribute, so you need the formatter function to format */
  formatter(name) {
	return (name.split(The '-') || []).reduce((t, c) = > t + upFirst(c), ' ')}}Copy the code

Taro’s native navigateTo method is not directly used within the tool. Instead, you need to manually configure the method. First, the routing API exported by Taro is not easy to use. Second, the API is encapsulated internally and the degree of customization is not high enough.

Shelljs makes script calls

In the file listener callback function, use shelljs to execute the generated command.

other

Several warehouses mentioned in this article are as follows:

  • Ts-morph modifies and generates typescript code
  • Chokidar listens for file changes
  • Webpack-plugin-chokidar Integrates Chokidar into Webpack and must be used in WebPack Dev mode
  • Generated code generation management tool
  • Generated -plugin-taro-router-service Modifies the code script