Use Taro to develop Hongmeng native applications - explore the working principle of adapting Hongmeng ArkTS

background

In the previous article, we already learned about Huawei’s upcoming pure-blood version of Hongmeng operating system, Hongmeng Next , as well as news about various Internet manufacturers developing Hongmeng applications. Among them, Taro, as an important front-end development framework, also actively adapts to Hongmeng’s new generation language framework-ArkTS.

This article will delve into the working principle of Taro's adaptation to the Hongmeng ArkTS framework. Next, let's take a look at the overall idea of ​​adaptation.

the whole idea

In terms of the overall idea of ​​adapting ArkTS, similar to adapting small programs, we give priority to a runtime-biased adaptation solution , mapping the Taro virtual DOM tree to the corresponding ArkTS UI component at runtime.

Reasons for choosing a partial runtime solution

1. The DSL paradigm of the front-end framework React/Vue and the UI paradigm of ArkTS are quite different.

Taking React as an example, we simply render a component on both React and ArkTS Button, and assign some simple style attributes to this component:

React VS ArkTS

It can be seen that in this simple Buttoncomponent example, the code structures on both sides are actually quite different. Not to mention that in actual projects, we also need to consider various loop bodies and expressions. If If these codes are parsed and converted at compile time, various errors and omissions will inevitably occur, and the readability of the converted code cannot be guaranteed.

In fact, this is also a microcosm of the upgrade from Taro 1/2 to Taro 3. The runtime-oriented adaptation solution can, on the one hand, bring a better user development experience without restricting developers' grammatical specifications. On the other hand, it is compatible with more web ecosystems and supports the operation of most existing open source tools and dependencies.

2. The partial runtime adaptation solution can inherit part of the runtime and compile-time logic of the small program

Another reason for choosing a runtime-biased adaptation solution is that the current Taro adaptation applet is taking a runtime-biased route. Therefore, if you also choose a runtime-biased solution when adapting Hongmeng ArkTS, some compilation in the front The real-time link and the runtime link are very similar, and even the adaptation of Hongmeng ArkTS can reuse the logic of some small programs.

Reuse module diagram

This reuse will bring two obvious benefits:

  1. The workload of adapting to Hongmeng ArkTS is reduced, and the function of adapting Taro to Hongmeng ArkTS can be put online earlier for developers to experience and use.

  2. Some subsequent performance optimizations or function additions to the mini program can be synchronized to the Hongmeng terminal synchronously or at minimal cost, and vice versa.

Design ideas for biased runtime solutions

The idea of ​​​​partial runtime can be summarized in one sentence, that is: simulate and implement the browser environment, so that React, Vue, and Web ecological libraries can run directly in the Hongmeng environment.

Schematic diagram

1. Simulate the BOM and DOM of a set of browsers in the Hongmeng environment

It is necessary to support the use of front-end frameworks such as React and Vue to develop Hongmeng applications. First, we need to simulate a set of browser BOM and DOM . BOM refers to some global objects that come with browsers such as windows, history, document, etc., and DOM refers to browsing. Some document node object models provided by the server, such as div, img, button, etc.

We need to simulate a set of BOM and DOM that can run in the Hongmeng environment to be used by the front-end framework layer, so that these Taro codes that depend on the browser environment can run on the Hongmeng app.

class TaroElement extends TaroNode {
  public _attrs: Record<string, string> = {}
  private _innerHTML: string = ''
  public readonly tagName: string

  constructor (tagName: string) {
    super()
    this.tagName = tagName
  }

  public set id (value: string) {}

  public get id (): string {}

  public set className (value: string) {}

  public get className (): string {}

  public get classList (): ClassList {}

  public get attributes (): NamedNodeMap {}

  public get children (): TaroElement[] {}

  public setAttribute (name: string, value: string): void {}

  public getAttribute (name: string): string | null {}

  public removeAttribute (name: string): void {}
}

2. Access these BOM and DOM through Reconciler

Similar to the mini program, by defining a custom hostconfig , some node operation logic related to the terminal side is separated from the core logic of the framework layer.

Taking the development of Hongmeng applications with the React framework as an example, we extracted some key operations of adding, deleting, modifying, and checking host environment nodes in React into a hostconfig . The logic in this hostconfig is bound to the virtual BOM and DOM we built.

After the binding is successful, the results of the addition, deletion, modification and check of the target node by the React project code will be directly reflected in the Taro virtual BOM and DOM we created.

hostconfig

3. Implement the bridge layer from virtual BOM and DOM to ArkTS

So far, after executing the front-end framework layer code, we can get a virtual DOM tree composed of these virtual DOMs.

(1) Page rendering

We will then pass this DOM tree to the page entry of the Hongmeng application, bind it to its member attribute node, trigger rendering, and then ArkTS will make a recursive rendering call based on this node tree to generate the corresponding native component. Thus rendering a specific page.

import { TaroElement } from "../../npm/@tarojs/runtime"
import { createNode } from "../../npm/@tarojs/components/render"

@Entry
@Component
struct Index {
  @State node: TaroElement = new TaroElement("Block")

  build() {
    createNode(this.node)
  }
}

Here structis a concept similar to the front-end Class, and @Componentit means that the current one structis a custom component, which can have its own buildmethod to build its own UI. Finally, @Entryit means that the current custom component is a page entry component, and the first one of all pages A component should @Entrystart with the component it is in.

(2) Page update

I believe you already have a basic concept of the first rendering process. So how does Taro implement the update mechanism of application page nodes?

When rendering for the first time, we will bind the corresponding event in the ArkTS UI component:

@Component
export default struct TaroVideoArkComponent {
  @ObjectLink node: TaroVideoElement

  build() {
    Video(this.getVideoData(this.node))
      .onClick((e: ClickEvent) => eventHandler(e, 'click', this.node))
      .props(this.getVideoProps())
      .attrs(getNormalAttributes(this.node))
  }
}

For example, the above-mentioned Video component will .onClickdeclaratively bind the click event. When the user clicks on the Video component in the application page, the callback of this event will be triggered, and the triggered eventHandlercall eventHandlerwill get the data collected in the Taro virtual DOM. Event listener callbacks and execute these callbacks.

The monitoring of events is performed at the front-end framework layer. Taking React as an example, React will commitUpdateparse events such as user-bound onClickevents in the Reconciler hook, and then addEventListenermonitor the events through the nodes.

Going back eventHandler, when eventHandlerthe event callback is executed, it may cause the front-end framework layer data status to be updated, which in turn causes the framework to call some logic that modifies the DOM tree nodes and DOM node attributes. Since these DOMs are simulated by Taro itself, they are created when The Observed decorator will be bound to the Observed decorator. This decorator will be used in conjunction with the @objectLink decorator to monitor changes in properties on the Taro DOM Node and trigger the call of the component's update method to achieve the purpose of updating.

// TaroVideoElement
@Observed
class TaroVideoElement extends TaroElement {
  constructor() {
    super('Video')
  }

  async play() {
    try {
      this._instance.controller.start()
      return Promise.resolve()
    } catch (e) {
      return Promise.reject(e)
    }
  }
  // ...
}

// TaroVideoArkComponent
@Component
export default struct TaroVideoArkComponent {
  @ObjectLink node: TaroVideoElement
  build() {
    Video(this.getVideoData(this.node))
      .defaultEvent()
      .props(this.getVideoProps())
      .attrs(getNormalAttributes(this.node))
  }
}

(3) Overall data structure conversion process

The overall data structure conversion process is as shown in the figure below, which will go through three stages:

  • First, it is processed by the front-end framework layer code. For example, in React, the original data will be processed by React into a Fiber node tree.

  • Secondly, under the action of Reconciler, the data in the framework layer will be converted into virtual DOM nodes created by Taro.

  • createNodeFinally, these nodes will become various corresponding ArkTS UI components through recursive calls of the UI construction function in Hongmeng .

Schematic diagram

4. Use ArkTS to implement content included in Taro components and API standards

So far, I believe everyone has understood how to use Taro to convert the front-end framework layer code into ArkUI code. Then we still need to deal with two issues at runtime:

  1. The components used by the front-end framework layer need to have corresponding implementations in ArkTS.
    As can be seen from the above process, each type of React HostComponent component needs to correspond to a type of TaroElement and a type of ArkComponent in the end, so we need to have a complete set of components for these different types of TaroElement and ArkComponent. accomplish.

  2. The API used by the front-end framework layer also needs to have a corresponding implementation in ArkTS.
    In addition to components, APIs also need to follow Taro's current standards. Use the APIs provided by Hongmeng environment to simulate and implement a set of Taro standard APIs, and bind these APIs to Taro's global objects and export them for users to use.

Generally speaking, the solution to these two problems is to use the native API and components provided by Hongmeng ArkTS to simulate and implement a set of APIs and components corresponding to the front-end framework layer. The specific implementation involves complex code details, which are not much in the article. It has been described, and friends who want to learn more can read and understand it by themselves in the source code repository.

5. Implement the engineering logic of Hongmeng platform

(1) Implement Hongmeng terminal platform plug-in

In Taro, each terminal has a corresponding platform for adaptation, such as the plug-in corresponding to the WeChat mini program platform @tarojs/plugin-platform-weappand the plug-in corresponding to the JD mini program platform @tarojs/plugin-platform-jd. Therefore, when Taro adapts to Hongmeng ArkTS, it will also build a new platform plug- @tarojs/plugin-platform-harmonyin. Users can When using Taro to develop Hongmeng applications, you only need to introduce this plug-in and execute the corresponding packaging command.

Each terminal can process compile-time and runtime logic according to the platform, and the things that each terminal platform plug-in has to handle are similar. Take the mini-program terminal platform as an example:
terminal platform

  1. Adjust the compile-time configuration, start the compilation process, and load the corresponding runner.

  2. Add or modify lifecycle, component name, component properties and API implementation at runtime.

  3. Customize and modify the mini program compilation template.

In the Hongmeng client platform, since components and APIs are re-implemented natively, all implemented components and APIs will be directly injected into the output directory during compilation , instead of being run like mini-program platform plug-ins. Therefore, in the Hongmeng terminal platform plug-in, the following two things are mainly done:

  1. Adjust the compile-time configuration, start the compilation process, and load the corresponding runner.

  2. Stores implemented components and APIs, waiting for acquisition and injection at compile time.

Hongmeng terminal platform plug-in

(2) Implement Hongmeng compilation and packaging function

As mentioned above, the Hongmeng platform plug-in will trigger Hongmeng's compilation and packaging process. In this process, Taro will use Vite (currently only Vite is supported) to package the project code, and finally output an executable Hongmeng project source. Code to the Hongmeng Project directory.

The packaging logic here is mainly divided into the following five parts:

  • a. Semi-compilation processing
    determines whether the user has enabled the mode in the JSX file compileMode. If so, parse the JSX template and generate the corresponding ETS template to optimize runtime performance. Since our solution will initialize many custom component instances
    during runtime , the main time-consuming of our solution is spent on this instantiation logic. Therefore, we will use a method similar to the small program semi-compilation solution during compilation. , generate corresponding template files for some code nodes that can be analyzed in advance, thereby reducing the number of instantiated custom components when the final page is rendered.

  • b. To parse TypeScript, JavaScript and other files
    , we need to use packaging tools to translate JSX written by users into TypeScript/JavaScript language that ArkTS can read through tools such as babel and swc, and analyze the dependencies introduced by these files. According to user configuration Or Taro's default rules generate corresponding chunks.

  • c. Style parsing and processing
    ArkTS does not support CSS files, so we also need to use packaging tools to process style files. We will analyze all JSX and TSX codes that reference CSS files during compilation.
    Then we will use Rust to develop a tool that parses React components and corresponding CSS files , calculates the final style for each React node, and applies it to scenarios such as React Native and Hongmeng that do not support CSS writing (currently only class name selectors are supported) .
    Finally, we will hand over these codes that reference CSS files to the style parsing tool. The tool will write these styles on these JSX nodes in the form of Style attributes, and return the final processed JSX and TSX codes to subsequent compilation operations.
    Style parsing

  • d. Based on app.config.jsthe ets entry file generated for the app and each page,
    we will app.config.jsgenerate the corresponding ets file according to the user's configuration, and generate a app.etsUIAbility component . The UIAbility component is the basic unit of system scheduling in ArkTS and provides a window for drawing the interface for the application. . In addition, one or more page ets files will be generated based on the page configuration in the configuration. It should be noted here that if tabbar is configured, all tabbar pages will be merged into one taro_tabbar.etsfile.

  • e. Inject glue code, runtime components and API.
    The glue code here refers to the connection code of React and ArkTS pages. Similar to the mini program, we will generate two objects app and page, and the app object will be app.etsinitialized in. It is used to control the injection and unloading of the page; the page object will be initialized in the ets file of the corresponding page, used to load the corresponding React page components, and trigger its various life cycles at the appropriate time.

Regarding the specific implementation of semi-compiled mode and style parsing, since the logic involved is relatively complex, we will not go into details in this article. We will introduce one article in the following Hongmeng series of articles . Those who want to know more Friends can wait patiently for the release of subsequent series of articles.

Use Cases

Currently, the Taro project only supports the use of React for the development of the Harmony project. The following is a simple code example.

import Taro from '@tarojs/taro'
import { View, Text, Image } from '@tarojs/components'

import { IMG } from './constant'

import './index.scss'

export default function Index() {
  return (
    <View className='index'>
      {/* 开启半编译模式 */}
      <View compileMode>
        <Text
          className='index-world'
          onClick={() => Taro.setBackgroundColor({ backgroundColor: 'red' })}
        >
          Hello,World
        </Text>
        <Image src={IMG} className='index-img' />
      </View>
    </View>
  )
}

In addition, we also simply imitated a cross-terminal e-commerce demo. You can see that the application and page effects of Taro on the H5 end, mini program end and Hongmeng end are basically the same after conversion.

And when rendering 1,000 nodes, the rendering time of Taro to Hongmeng APP is about 300ms longer than the original one , and this performance gap will be greatly reduced again through dynamic attributes and node mapping optimization in the future , and it is expected to be reduced to 100ms- About 200ms .
Comparison chart

Usage restrictions

At present, although the work of adapting Taro to Hongmeng ArkTS has been basically completed, during the adaptation process, we also discovered some remaining issues that cannot be solved temporarily or are planned to be solved later.

There are certain limitations in style parsing

Since in ArkTS, declarative UI is used to describe the style of the UI, there are no style files such as sass and css. Therefore, when Taro adapts to Hongmeng ArkTS, it will parse these style files at compile time. And write these styles inline into the TS/JS code of the component.
Normal styles are based on W3C specifications, and there are behaviors of class name cascading and style inheritance . Due to the different writing methods of developers in the code, Taro has no way to obtain accurate node structure and node class name information at compile time, so it cannot support it. these two behaviors.
In addition, since the parsing of styles is based on the latitude of the component file, the style file can only be applied to the component file referenced by it, but cannot be applied across files , and the style file only supports class selectors .

Components and APIs have usage restrictions

Since there are major differences between the Hongmeng platform and the mini program platform, some components and API specifications of the mini programs cannot be re-implemented on the Hongmeng platform, such as APIs related to login and account information, live-player, etc. Live broadcast related components.

Summary and Outlook

This article provides an in-depth analysis of how the Taro framework adapts to the new generation language framework ArkTS under Huawei's Hongmeng operating system, highlighting the runtime adaptation strategy to reduce conversion errors and omissions during compilation and optimize the developer experience. It was explained in detail that Taro enables front-end frameworks such as React to run on Hongmeng applications by simulating the BOM and DOM in the browser environment, bridging the virtual DOM built by Taro and ArkTS components, and using the semi-compiled mode in engineering and style parsing capabilities.

Follow-up planning

Support dynamic functions

Currently, the Hongmeng application developed by Taro can only be released with the release of the Native package. It does not support pulling down the RN package when running Native like RN. Therefore, for now, Taro will also be dynamic. This feature is designated as one of the key goals for subsequent iterations.

Support native hybrid compilation

In projects that use Taro to develop small programs, in addition to the basic compilation and packaging functions, the most commonly used function is the native mixing function, which allows developers to package Taro projects into native pages and components for mixing with native projects.
In the process of adapting to Hongmeng, we also received many suggestions from small partners in the industry, hoping to use this function in the Hongmeng environment. Therefore, the Taro team will also put this requirement at a higher priority in the future and strive to implement it next time. This feature will be added in the iteration.

write at the end

In the future, the Taro team will continue to maintain this adaptation solution, listen to community feedback, continuously improve application performance and improve developers' development experience, and truly achieve a seamless experience of one set of code and multiple terminals running.

Author: JD Retail Xuan Zebin

Source: JD Cloud Developer Community Please indicate the source when reprinting

The author of a well-known open source project lost his job due to mania - "Seeking money online" No Star, No Fix 2023 The world's top ten engineering achievements are released: ChatGPT, Hongmeng Operating System, China Space Station and other selected ByteDance were "banned" by OpenAI. Google announces the most popular Chrome extension in 2023 Academician Ni Guangnan: I hope domestic SSD will replace imported HDD to unlock Xiaomi mobile phone BL? First, do a Java programmer interview question. Arm laid off more than 70 Chinese engineers and planned to reorganize its Chinese software business. OpenKylin 2.0 reveals | UKUI 4.10 double diamond design, beautiful and high-quality! Manjaro 23.1 released, codenamed “Vulcan”
{{o.name}}
{{m.name}}

Supongo que te gusta

Origin my.oschina.net/u/4090830/blog/10322924
Recomendado
Clasificación