辛宝Otto

辛宝Otto 的玄酒清谈

北漂前端程序员儿 / 探索新事物 / Web Worker 主播之一/内向话痨
xiaoyuzhou
email

How does the SpeedPass-TinyVue component library support Vue 2, Vue 3, React, and Solid at the same time?

Quick Review - How TinyVue Component Library Supports Vue2, Vue3, React, Solid

Reference: "How TinyVue Component Library Implements Cross-Framework (Vue2, Vue3, React, Solid)?"

This article introduces the necessity and practical operation of a cross-framework component library. The title caught my interest, so I'll provide a quick review. I will quote the original article, and my understanding and thoughts will be marked as my own.

Background#

OpenTiny is a component library developed by Huawei, which includes TinyNG, TinyVue, TinyEngine, and other components.

The ability to output a unified set of component libraries and APIs that can be used across different technology stacks can enhance user confidence, increase development efficiency, and achieve consistent UI performance across different technology stacks. Additionally, it helps establish a reputation for your own component library and explore potential users.

Of course, there are challenges involved. It requires abstracting logic and smoothing out differences between different solutions.

Architecture Diagram

This is the architecture diagram provided by the official source. The diagram and the article may not be very well-explained, but "Talk is cheap, show me the code." The article provides a GitHub repository demo that can help with understanding.

The article mentions two technologies or approaches, abstracted as follows:

  • Common adaptation layer
  • Renderless layer without rendering logic

For example, a tab menu or button can be divided into UI presentation and logic. UI presentation can be classified under the common adaptation layer, while inputs and outputs can be classified under the logic layer.

Technical Implementation#

Using pnpm + monorepo to manage the component library.

Technical implementation approach:

Environment Setup#

Create a monorepo environment.

Prepare different scripts, such as vue3, vue2, react, solid, and use micro-frontends to achieve management without boundaries.

Dependency Handling#

Some dependencies need to be differentiated between Vue2 and Vue3, so pnpm.packageExtensions is used for differentiation, which is a usage I haven't seen before.

  • The article gives an example of how to simultaneously support React and Solid. First, define react-button and solid-button.
  • Also, create the packages/components/{platform}/common folder.
  • Interestingly, the article mentions the purpose of the ahooks dependency, which is to provide reactive capabilities in React similar to Vue's reactive data. It's funny to see that: https://ahooks.gitee.io/zh-CN/hooks/use-reactive

Dependency Handling Example

  • Solid itself is based on Signal and comes with reactivity.
  • React uses ahooks to simulate reactive data.
  • Simulating Vue's emit.
  • Simulating Vue's nextTick.

The article provides an example of how to write React and Solid code, implementing emit, useNextTick, and useSetup, where useSetup returns the content of the render method.

Code is omitted.

Understanding Renderless Logic#

This part of the code can be divided into two parts:

  • Framework-related entry functions
  • Framework-independent pure functions

The article is not very clear, and after reading it several times, I'm still a bit confused. It may require practical implementation to fully understand.

Taking the button component as an example, it needs to implement the click event and the timer for disabling repeated clicks on different platforms.

For example, in the renderless approach, how to write code for React and Solid is similar. Both need to implement the renderless method, which returns the state and the methods that need to be referenced, such as handleClick and timer. Since this is the adaptation layer, it only focuses on defining common state and framework-related methods.

In the index file, the framework-independent logic is implemented. Here, the handleClick and timer related logic is implemented.

For the button component:

  • In react.js and solid.js, state management and click timer methods are implemented.
  • The specific implementation of click and timer is done in index.js using a framework-independent approach.

The general understanding of how the logic is implemented is as follows. Next is the UI presentation, which doesn't involve any black magic. It's just implementing the render method, but React and Vue both support JSX, so the logic is similar.

In the end, a demo example is provided, which makes it much clearer:
https://github.com/opentiny/cross-framework-component

Demo Example

Taking packages/components/react as an example, this is the demo content of the React component library. You can see the common/src/index.js file, which is used to simulate framework differences and define useSetup. It also exists in Solid, Vue2, and Vue3.

Next, look at src/button/src/pc.jsx, which defines the UI presentation of the button component.

These two files define the UI part. How is the logic part handled? Let's look at the following diagram:

Logic Implementation

Inside renderless/src/button is the logic of the button component. The common part is placed in index.js, and the adaptation part is placed in react.js.

Continuing with the example, how is the button component defined in Vue? It is defined in both vue/button and vue/common.

Vue Button Component

Earlier, I mentioned micro-frontends, which is used to create a playground and display different framework effects on a single page.

Micro-frontends

This corresponds to the packages/home directory. Here, the micro-frontend wujie is used to embed different pages.

Micro-frontend Example

Outlook#

This demonstrates a design approach for components, abstracting and smoothing out differences.

Given the opportunity, further understanding can be achieved.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.