title: Write Platform plugins

Extending a compiled platform requires writing a Taro plugin for compile-time and run-time compatibility respectively.

Platform Plugin Architecture

Plugin Directory

Using @tarojs/plugin-platform-weapp as an example.

  1. ├── src Source code directory
  2. | ├── index.ts Plugin entry
  3. | ├── program.ts Compile entry
  4. | ├── template.ts Template handling
  5. | ├── runtime.ts Runtime entry
  6. | ├── runtime-utils.ts Runtime dependency tools
  7. | ├── apis.ts API related processing
  8. | ├── apis-list.ts API list
  9. | ├── components.ts Component list
  10. | └── components-react.ts Types of components for React to use
  11. ├── types Type
  12. ├── index.js Compile-time entry
  13. ├── tsconfig.json
  14. ├── rollup.config.json
  15. ├── package.json
  16. └── README.md

Architecture Diagram

Write Platform plugins - 图1

Compile Time

Handles compile-related operations such as Webpack configuration, template generation rules, etc.

一、Writing Taro plugins

Pre-reading: [How to Write a Taro Plugin]

First we need to write a Taro plugin to register our compilation platform, eg.

```js title=”index.ts” export default (ctx) => { ctx.registerPlatform({ name: ‘weapp’, useConfigName: ‘mini’, async fn (arg) { // … } }) }

  1. #### ctx.registerPlatform(options: object)
  2. Register a compilation platform
  3. ##### options.name
  4. `string`
  5. The platform name for the CLI compile command.
  6. If 'xxx' is configured, the CLI command to use when compiling this platform:
  7. ```shell
  8. taro build --type xxx
  9. taro build --type xxx --watch
options.useConfigName

string

Incorporate the specified fields from the Taro compilation configuration into the compilation.

Taro minn program related configuration is placed under the mini field by default, so in general it is sufficient to configure usingConfigName: mini.

options.fn(arg)

function

The entry function for platform compilation accepts an argument arg, in which we can start writing the logic for end-platform compilation.

arg

object

Integrate the above options.useConfigName specified fields, see compilation configuration details.

二、Writing platform classes

Next add to the plugin entry function mentioned in the previous section.

We abstracted the logic commonly used at compile time into a base class TaroPlatformBase, which developers can inherit from this base class to enable platform compilation.

The compilation interface of the above custom platform class is then called in the plugin entry function as follows.

```js title=”index.ts” import Weapp from ‘./program’

export default (ctx) => { ctx.registerPlatform({ name: ‘weapp’, useConfigName: ‘mini’, async fn (arg) { // Call the start function of the custom platform class to start platform compilation const program = new Weapp(ctx, config) await program.start() } }) }

  1. ## Runtime
  2. Handles runtime-related operations such as APIs, components, Taro runtime logic, etc.
  3. ### 一、Handling Of Runtime Entry
  4. #### 1. Writing runtime.ts
  5. `runtime.ts` is our runtime entry file, which `Webpack` will inject into `app.js` for reference when it is compiled.
  6. Example:
  7. ```js title="runtime.ts"
  8. import { mergeReconciler, mergeInternalComponents } from '@tarojs/shared'
  9. import { hostConfig, components } from './runtime-utils'
  10. mergeReconciler(hostConfig)
  11. mergeInternalComponents(components)

```js title=”runtime-utils.ts” export * from ‘./components’ export const hostConfig = {}

  1. `runtime.ts` responsibilities:
  2. * Use the `mergeReconciler` function to merge the custom `hostConfig` into the global [Reconciler](./platform-plugin-reconciler).
  3. * Use the `mergeInternalComponents` function to merge custom component information [components.ts]($i18n-en-docusaurus-plugin-content-docs-current-platform-plugin-base#31-write-componentsts) into the global `internalComponents` component information object.
  4. > The runtime-utils.ts is extracted to make it easier for other plugins to reference
  5. #### 2. Connection Plugin Entry
  6. In order for `Webpack` to know where to refer to the above runtime entry files, `runtimePath` needs to be configured.
  7. ```js title="program.ts"
  8. class Weapp extends TaroPlatformBase {
  9. runtimePath = '@tarojs/plugin-platform-weapp/dist/runtime'
  10. }

二、Handling API

In Taro, users need to refer to Taro’s built-in API and the Promise-ified mini program API from @tarojs/taro.

  1. import Taro from '@tarojs/taro'
  2. // API
  3. Taro.getCurrentInstance()
  4. // Mini program API
  5. Taro.request()

1. Configure initNativeApi

The original @tarojs/taro package only provides the built-in API, we need to add the API for the mini program and the API we want to mount on the Taro object by configuring Reconciler with initNativeApi option to add APIs for mini program to the global Taro object and the APIs we want to mount on the Taro object.

``js title="apis-list.ts" // When additional native APIs need to be added, splitting a separateapis-list.ts` file can be beneficial for maintenance.

// Synchronization API export const noPromiseApis = new Set([ ‘getAccountInfoSync’ ])

// Asynchronous APIs, which can set success, fail, and complete callbacks, need to be Promiseized. export const needPromiseApis = new Set([ ‘addCard’ ])

  1. ```js title="apis.ts"
  2. import { processApis } from '@tarojs/shared'
  3. import { noPromiseApis, needPromiseApis } from './apis-list'
  4. declare const wx: any
  5. export function initNativeApi (taro) {
  6. // The following section describes the processApis function in detail
  7. processApis(taro, wx, {
  8. noPromiseApis,
  9. needPromiseApis
  10. })
  11. // Any API that can be mounted for taro
  12. taro.cloud = wx.cloud
  13. }

```js title=”runtime-utils.ts” import { initNativeApi } from ‘./apis’ export const hostConfig = { initNativeApi }

  1. #### 2. processApis(taro, global, options)
  2. ##### Parameters
  3. | Parameters | Type | Description |
  4. | :--- | :--- | :--- |
  5. | taro | object | Taro Object |
  6. | global | object | Mini Program global objects, such as WeChat wx |
  7. | options | object | Configuration items |
  8. ###### options
  9. | Parameters | Type | Description |
  10. | :--- | :--- | :--- |
  11. | noPromiseApis | Set`<string>` | New Synchronization API |
  12. | needPromiseApis | Set`<string>` | New Asynchronous API |
  13. The above `processApis` function helps us do three things.
  14. 1. mount all of the platform's common mini program APIs onto a Taro object
  15. 2. mount the common mini program global object properties on the Taro object
  16. 3. mount the user-input mini program API on the Taro object
  17. ## Build Packages
  18. The plugin is packaged using `Rollup` and requires the following files to be packaged out.
  19. | Entry file | Mode | Required | Description |
  20. | :--- | :--- | :--- | :--- |
  21. | src/index.ts | cjs | YES | Plugin entry for Taro CLI parsing |
  22. | src/runtime.ts | es | YES | Runtime entry |
  23. | src/runtime-utils.ts | es | NO | Collection of runtime tools for reference by inherited subclasses |
  24. | src/components-react.ts | es | NO | Need to be implemented when there are new components for React to reference |
  25. Note that Taro-related packages need to be configured with `external` to avoid repackaging.
  26. ```js title="rollup.config.js"
  27. {
  28. external: ['@tarojs/shared', '@tarojs/service']
  29. }

Types

The types maintained by the Taro core library may not include components and APIs added by the current plugin, in which case we need to perform [module augmentation (module augmentation)] for @tarojs/taro and @tarojs/components (https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation).

Create a type definition file:

```ts title=”types/shims-iot.d.ts” // Extend new APIs and component definitions for Alipay IOT mini program import { ComponentType } from ‘react’ import Taro from ‘@tarojs/taro’

declare module ‘@tarojs/taro’ { namespace ix { function onCashierEventReceive (cb: any): void } }

interface PosterProps { posid: string audible?: boolean onSuccess?: () => void onFail?: () => void onChange?: () => void }

declare module ‘@tarojs/components’ { export const Poster: ComponentType }

  1. The developer can simply introduce this file in the type definition file.
  2. ```ts title="global.d.ts"
  3. /// <reference path="node_modules/@tarojs/plugin-platform-alipay-iot/types/shims-iot.d.ts" />