title: TaroPlatformBase

We have abstracted the common compile-time logic into a base class TaroPlatformBase, which developers can inherit from to achieve platform compilation.

For example, we create a WeChat mini program platform.

```js title=”program.ts” import { TaroPlatformBase } from ‘@tarojs/service’ export default class Weapp extends TaroPlatformBase { // … }

  1. ## Methods and Properties
  2. ### constructor (ctx, config)
  3. constructor, accepting two parameters.
  4. | Parameter | Type | Description |
  5. | :--- | :--- | :--- |
  6. | ctx | object | Plugin context object |
  7. | config | object | Taro compilation configuration |
  8. ### ctx
  9. `object`
  10. Plugin context object
  11. #### this.ctx.modifyWebpackChain
  12. Get WebpackChainfor example:
  13. ```js title="program.ts"
  14. class Weapp extends TaroPlatformBase {
  15. modifyWebpackChain () {
  16. // The WebpackChain instance can be obtained through this.ctx.modifyWepackChain
  17. this.ctx.modifyWebpackChain(({ chain }) => {
  18. // chain.xxxx
  19. })
  20. }
  21. }

helper

object

Holds a set of tool functions corresponding to the exported contents of the @tarojs/helper package.

config

object

Compile the configuration object.

(abstract) platform

Abstract properties, which subclasses must implement.

string

Platform names, eg:

```js title=”program.ts” class Weapp extends TaroPlatformBase { platform = ‘weapp’ }

  1. ### (abstract) globalObject
  2. > Abstract properties, which subclasses must implement.
  3. `string`
  4. Global object names for the various APIs mounted by the mini program. For example, `wx` for WeChat mini program, `my` for Alipay mini program, eg.
  5. ```js title="program.ts"
  6. class Weapp extends TaroPlatformBase {
  7. globalObject = 'wx'
  8. }

(abstract) runtimePath

Abstract properties, which subclasses must implement.

stirng | string[]

The parsing path of the runtime file compiled by the mini program, eg.

```js title=”program.ts” class Weapp extends TaroPlatformBase { runtimePath = ‘@tarojs/plugin-platform-weapp/dist/runtime’ }

  1. ### (abstract) fileType
  2. > Abstract properties, which subclasses must implement.
  3. `object`
  4. The suffix names of various files of the platform, eg.
  5. ```js title="program.ts"
  6. class Weapp extends TaroPlatformBase {
  7. fileType = {
  8. // Template file suffixes
  9. templ: '.wxml',
  10. // Style file suffix
  11. style: '.wxss',
  12. // Configuration file suffix
  13. config: '.json',
  14. // Script file suffix
  15. script: '.js',
  16. // 【[Optional] Rendering layer script file suffix, such as wxs for WeChat mini program, sjs for Alipay mini program
  17. xs: '.wxs'
  18. }
  19. }

(abstract) template

Abstract properties, which subclasses must implement.

object

The template object instance.

(optional) projectConfigJson

Subclasses can optionally be set or not.

The name of the mini program configuration file.

If the subclass has an implementation of projectConfigJson, this file will be automatically copied to the dist directory.

```js title=”program.ts” class Weapp extends TaroPlatformBase { projectConfigJson = ‘project.config.json’ }

  1. ### (optional) taroComponentsPath
  2. > Subclasses can optionally be set or not.
  3. Compile-time alias for the `@tarojs/components` package, described in detail below.
  4. ```js title="program.ts"
  5. class Weapp extends TaroPlatformBase {
  6. taroComponentsPath = '@tarojs/plugin-platform-weapp/dist/components-react'
  7. }

setupTransaction

Transaction hooks for the setup phase.

```js title=”program.ts” class Weapp extends TaroPlatformBase { /**

    1. setupTransaction - init
    1. setup
    1. setupTransaction - close
    1. buildTransaction - init
    1. build
    1. buildTransaction - close */ constructor (ctx, config) { super(ctx, config)

    this.setupTransaction.addWrapper({ init () {} close () {} }) } } ```

buildTransaction

The transaction hook for the build phase.

```js title=”program.ts” class Weapp extends TaroPlatformBase { /**

    1. setupTransaction - init
    1. setup
    1. setupTransaction - close
    1. buildTransaction - init
    1. build
    1. buildTransaction - close */ constructor (ctx, config) { super(ctx, config)

    this.buildTransaction.addWrapper({ init () {} close () {} }) } } ```

start ()

The plugin entry calls the start method to open the build, eg.

```js title=”program.ts” class Weapp extends TaroPlatformBase { // … }

export default (ctx) => { ctx.registerPlatform({ name: ‘weapp’, useConfigName: ‘mini’, async fn ({ config }) { const program = new Weapp(ctx, config) await program.start() } }) }

  1. ### generateProjectConfig (src, dist)
  2. For generating a project configuration file like project.config.json.
  3. | Parameters | Type | Default | description |
  4. | :--- | :--- | :--- | :--- |
  5. | src | string | | The name of the configuration file in the project source code |
  6. | dist | string | 'project.config.json' | The name of the compiled configuration file |
  7. Example:
  8. ```js
  9. // Export user-written `project.tt.json` to `project.config.json`
  10. generateProjectConfig('project.tt.json')
  11. // Export user-written `project.swan.json` to `project.swan.json`
  12. generateProjectConfig('project.swan.json', 'project.swan.json')

recursiveReplaceObjectKeys (target, keyMap)

Recursively replace the key value of the target object.

Parameters Type description
target object Target object
keyMap object Rules for replacing key values

Example, Alipay mini program configuration item key value is different from the specification of most mini program and needs to be aligned.

  1. // this.ctx.modifyMiniConfigs can get the list of mini program entry and page configuration files
  2. this.ctx.modifyMiniConfigs(({ configMap }) => {
  3. const replaceKeyMap = {
  4. navigationBarTitleText: 'defaultTitle',
  5. navigationBarBackgroundColor: 'titleBarColor',
  6. enablePullDownRefresh: 'pullRefresh',
  7. list: 'items',
  8. text: 'name',
  9. iconPath: 'icon',
  10. selectedIconPath: 'activeIcon',
  11. color: 'textColor'
  12. }
  13. Object.keys(configMap).forEach(key => {
  14. const item = configMap[key]
  15. if (item.content) {
  16. // Recursively replace the key value in the configuration file with the key value of the target object
  17. this.recursiveReplaceObjectKeys(item.content, replaceKeyMap)
  18. }
  19. })
  20. })

Custom Platform Classes

The next section will describe how to create a custom platform class, using the example of extending compilation support for WeChat mini prpgram.

1. Inheritance of base class

Inherit TaroPlatformBase to implement the Weapp class and implement all abstract properties, optional properties.

```js title=”program.ts” import { TaroPlatformBase } from ‘@tarojs/service’

const PACKAGE_NAME = ‘@tarojs/plugin-platform-weapp’

class Weapp extends TaroPlatformBase { // Platform Name platform = ‘weapp’ // Mini program global object globalObject = ‘wx’ // The parsed path to the compiled runtime file of the mini program runtimePath = ${PACKAGE_NAME}/dist/runtime // File suffix fileType = { templ: ‘.wxml’, style: ‘.wxss’, config: ‘.json’, script: ‘.js’, xs: ‘.wxs’ } template = new Template() // Mini program configuration file name projectConfigJson = ‘project.config.json’ // alias path to the @tarojs/components package taroComponentsPath = ${PACKAGE_NAME}/dist/components-react

constructor (ctx, config) { super(ctx, config)

  1. /**
  2. * 1. setupTransaction - init
  3. * 2. setup
  4. * 3. setupTransaction - close
  5. * 4. buildTransaction - init
  6. * 5. build
  7. * 6. buildTransaction - close
  8. */
  9. // Custom logic can be injected at different stages of setup
  10. this.setupTransaction.addWrapper({
  11. init () {}
  12. close () {}
  13. })
  14. // Custom logic can be injected at different stages of build
  15. this.buildTransaction.addWrapper({
  16. init () {}
  17. close () {}
  18. })

} }

export default Weapp

  1. ### 2. Handling Template
  2. Write a [template class]($i18n-en-docusaurus-plugin-content-docs-version-3.x-platform-plugin-template) to handle template logic, setting its instance to the `template` property of the custom platform class.
  3. ```js title="program.ts"
  4. import { Template } from './template'
  5. class Weapp extends TaroPlatformBase {
  6. // ...
  7. // Template Instance
  8. template = new Template()
  9. }

3. Handle Component

We have compared the components and component properties of the 6 currently supported mini program to come up with a list of the most common components and their properties. Accessing the internalComponents property of the Template class instance to get these common components and their properties.

The purpose of extracting this generic component is to generate templates for mini program B that contain as few components or properties as possible that are unique to mini program A.

However, as each mini program platform develops, each platform may add some new components or attributes on its own. In this case, our platform plugin needs to handle these special components or properties by modifying template.internalComponents.

3.1 Write components.ts

components.ts can export an object to represent the modification of properties, the addition of new properties or the addition of new components to internalComponents.

Specification:

```js title=”components.ts” import { singleQuote } from ‘@tarojs/shared’

export const components = { // Component Name CamelCase ScrollView: // Property { // An empty string for value means that no default value is set ‘scroll-left’: ‘’, // when the default value of the property is a boolean or a number, the value is written as a string ‘enable-flex’: ‘false’, ‘refresher-threshold’: ‘45’, // When the default value of a property is a string, it needs to be wrapped with the singleQuote function ‘refresher-default-style’: singleQuote(‘black’), // Event bindRefresherAbort: ‘’ } }

  1. #### 3.2 Merge to template.internalComponents
  2. Once you have written `components.ts`, you can merge them with the `mergeComponents` method of the `Template` class instance.
  3. ##### template.mergeComponents (ctx, patch)
  4. Merge the component patch to `this.internalComponents`.
  5. | Parameters | Type | description |
  6. | :--- | :--- | :--- |
  7. | ctx | object | Plugin context object |
  8. | patch | object | Component patch |
  9. Example:
  10. ```js title="program.ts"
  11. import { components } from './components'
  12. class Weapp extends TaroPlatformBase {
  13. constructor (ctx, config) {
  14. super(ctx, config)
  15. // At the end of the setup phase, modify the template
  16. this.setupTransaction.addWrapper({
  17. close: this.modifyTemplate
  18. })
  19. }
  20. modifyTemplate () {
  21. this.template.mergeComponents(this.ctx, components)
  22. }
  23. }

```js title=”components.ts” export const components = { ScrollView: { ‘enable-flex’: ‘true’, ‘refresher-threshold’: ‘45’ }, Xyz: { ‘a’: ‘’ } }

  1. Assuming that the default value of `template.internalComponent` :
  2. ```js
  3. internalComponent = {
  4. ScrollView: {
  5. 'scroll-left': '',
  6. 'enable-flex': 'false',
  7. }
  8. }

The result of the consolidation:

  1. internalComponent = {
  2. ScrollView: {
  3. 'scroll-left': '',
  4. // enable-flex defalult value
  5. 'enable-flex': 'true',
  6. // added refresher-threshold property
  7. 'refresher-threshold': '45'
  8. },
  9. // add Xyz component
  10. Xyz: {
  11. 'a': ''
  12. }
  13. }

3.3 Directly modify template.internalComponents

In addition to merging with template.mergeComponents, we can also modify template.internalComponents directly.

```js title=”program.ts” class Weapp extends TaroPlatformBase { modifyTemplate () { // Remove some properties from the Slider component this.modifySlider(this.template.internalComponents.Slider) // Rewrite the property object of the View component this.template.internalComponents.View = {} }

modifySlider (slider) { delete slider[‘block-size’] delete slider[‘block-color’] } }

  1. > It is recommended to try to write a copy of `components.ts` for merge, rather than doing it directly. Since the merged component information is also needed at runtime, writing a single copy of `components.ts` can be reused.
  2. #### 3.4 Write components-react.ts
  3. When using React in Taro, the built-in components need to be referenced from `@tarojs/components` before they can be used.
  4. ```js
  5. import { View } from '@tarojs/components'

But if we add new built-in components, then we can’t fetch them from @tarojs/components.

So when we add new components, we need to write a components-react.ts and configure the Webpack alias for React to reference.

Example:

  1. Write components-react.ts file

```js title=”components-react.ts” // Original components export * from ‘@tarojs/components/mini’ // New components export const Editor = ‘editor’ export const OfficialAccount = ‘official-account’

  1. 2. Set [taroComponentsPath](./platform-plugin-base#optional-tarocomponentspath)
  2. ```js title="program.ts"
  3. const PACKAGE_NAME = '@tarojs/plugin-platform-weapp'
  4. class Weapp extends TaroPlatformBase {
  5. taroComponentsPath = `${PACKAGE_NAME}/dist/components-react`
  6. }