By Fengshui
Last year, an article titled, "What Should a Good Component be Like" was posted. It defined the type of PropTypes of React components and extracted their annotations with TypeScript AST syntax tree parsing, automatically generating the information corresponding to screenshots, usage, parameter descriptions, README, and DEMO. The article received good responses in the community and achieved satisfactory results for the team in practice as well. Now, it has accumulated over 1,000 React components in the internal component system.
Previously, an archetype and tool kit for developing React components was made with the help of webpack and TypeScript. If developers want to develop new components, they can use the archetype to initialize the corresponding project structure for development.
Component development will encounter many problems in internal component management and cumulation, such as no detailed information on components, missing component parameter documents, missing component usage documents, missing component demos, unindexable components, and non-standardized components products. Although the main path solves the problems mentioned above, Webpack's solution will always have an additional compilation layer for component development. When the compilation of a component library exceeds over 300, the growing number of dependencies introduced causes a load on the compilation of the components, resulting in a lower development experience for the developer.
It is no exaggeration to say that Vite has brought a revolutionary change to the frontend.
Vite combined the advanced tools and ideas of JS compilation development in communities, such as esbuild, Browser modules, HMR, and Pre-Bundling, which brought revolutionary changes to frontend development.
A long time ago, I said the most valuable element of any framework or library is not its code but the new ideas and inspirations behind it. Therefore, when I write articles, I also attach great importance to explaining the entire process and practice by making it clear what my actual thought process look like.
Vite is so fast because of the pre-bundle dependencies of esbuild and the dynamic compilation of browser-native ESM. For more details, please refer to Vite: The Problems.
With this idea in mind, it can be found that the following issues are highly consistent with the component development scenario:
Therefore, the previous thinking like StoryBook and the previous definitions used to extract the tsx component types will undergo a relatively big change.
Previously, a plugin, comprising type data for component input parameters, was made at the webpack level to dynamically analyze the exported tsx component. The static property variable __docgenInfo
is added dynamically to such a component. Furthermore, type data and annotation information obtained from AST analysis will be injected into JS Bundle for further processing into dynamic parameter settings:
Definition of component Props by TypeScript:
Analyze the content injected into JS Bundle:
Analyze the parameter interaction settings achieved after the transition:
Therefore, obtaining the metadata defined by this type is redundant for the component. Whether the metadata of the component is used or not, it will be parsed, extracted, and injected into the component Bundle during Webpack compilation. This process is inefficient.
Based on Vite, it is sufficient to obtain the information of component metadata when the metadata is used. For example, loading a React component as:
import ReactComponent from './Component1.tsx'
Then, load its metadata:
import ComponentTypeInfo from './component1.tsx.type.json';
// or
const ComponentTypeInfoPromise = import ('./component1.tsx.type.json');
Load the file type. type.json
through the Rollup plugin in Vite to parse the metadata of the corresponding component. At the same time, the HMR of component type changes can be achieved with the help of the Rollup's ability to collect compilation dependencies and HMR.
The section above is a preliminary idea inspired by the module loading of Vite.
However, if users want to develop a Vite-based development kit for React and Rax components (in addition to acquiring the component input parameter metadata), other problems need to be solved. The most important one is .md file parsing.
Based on the component development ideas provided by dumi and Icework, component usage can be written into any .md file through Markdown. Then, the compiler can dynamically parse the code blocks for jsx, tsx, css, scss, and less. Then, you can run them on the page after compiling them as an executable script.
By doing so, users can write a document and run and debug the component under different input parameters. The component performance can be written in different blocks and viewed by users themselves. What an amazing design idea!
Furthermore, if combined with the esbuild dynamic loading and HMR capabilities of Vite mentioned above, the entire component development experience will witness a significant improvement.
Therefore, a Vite plugin is required for the Markdown file to parse and load .md files. The expected capabilities are listed below:
import { content, modules } from "./component1/README.md";
// content The source content of README.md
// modules Running modules with `jsx`,`tsx`,`css`,`scss`,`less` obtained by parsing
The expected effect is shown in the picture below; please click to enlarge it:
How should a regular component library directory look? The directory structure of different components is similar whether in a separate component repository or an existing business project:
components
├── component1
│ ├── README.md
│ ├── index.scss
│ └── index.tsx
├── component2
│ ├── README.md
│ ├── index.scss
│ └── index.tsx
It is expected that users can start component development mode in any project. After running the Vite-comp, users can see a component-specific interface that has parsed and rendered the component Usage written in README.md and the interface defined by index.tsx. Thus, users only need to access different file paths to view the representation of corresponding components.
At the same time, it can help users compile and package all the content on this interface before posting the screenshots to NPM. When others see this component, they will see its information clearly, such as component input parameters, usage, and screenshots. Moreover, they can even open the Demo address and modify the component parameters to view the performance of the component in different states.
To achieve such an effect, a set of Runtime components are required so that React components, README.md, and TypeScript type definitions can be coordinated to concatenate into the component development page with component debugging and documentation.
In such a Runtime, it is also necessary to employ module parsing of Vite to convert its request with a URL of *//(README|*).html
into an accessible component Runtime HTML that is returned to the browser. This allows the browser to run the real component development page.
http: //localhost:7000/components/component1/ README.html
->
/components/component1/README.html
->
/components/component1/README.md
->
Runtime Html
As mentioned above, if the component props interface for tsx is added with Vite and this component type is parsed, it can also be used as a standalone plugin to parse file types ending in .tsx.type.json
. By importing this type of file, the compiler is allowed to dynamically parse the TypeScript types defined in its tsx files and return them to the frontend for consumption as modules.
The loading process can be seen as a virtual module, which means users can directly import a virtual file address to obtain the metadata of the corresponding React component:
// React Component
Import Component from './Component1.tsx';
// React Component Props Interface
Import ComponentTypeInfo from './component1.tsx.type.json';
// or
const ComponentTypeInfoPromise = import ('./component1.tsx.type.json');
Since this parsing capability does not occur with esbuild, the conversion performance cannot be synchronized with the compilation of the component main flow.
When a request is sent for this file type, a new thread needs to be launched to compile the content in the Serve mode of Vite. The whole process is asynchronous and does not affect the rendering progress of the component main flow. When a response to the request is returned, it is used to render the definition of the component Props and the sidebar panel.
In the process of HRM, it is also necessary to consider whether the tsx file modification involves the type changes of TypeScript. If the modification is found to cause type changes, the HMR event is triggered to update the modules.
All the above are cases where the component is in the Serve state, which is the development state of Vite. In the previous section, the loading capability of the es module of the browser was applied with the help of Vite. Therefore, the extension of dynamic loading capability at the development state can be performed.
However, Vite does not initiate Server services during the final build of the component, nor is it dynamically loaded with a browser. Therefore, it is required to consider compiling an HTML that can be run by the browser for the component to help users see the developed components and experience the process of debugging components during development.
So, in the development process of Vite plugins, compilation paths in the Build state need to be considered. If Vite will use the compilation capability of Rollup in the Build state, it is essential to consider manually providing rollup.input(entries)
for all components.
During the plugin writing process, the plugin loading lifecycle provided by Rollup must be followed to ensure that the module loading logic and compilation logic of the Build and Serve processes are consistent.
In the previous implementation process, I didn't thoroughly understand the relationship between Vite and Rollup. So, I relied much on the service-side middleware capabilities provided by Vite Server. As a result, I didn't realize problems until the Build state was considered, and the previous loading logic was almost rewritten.
I will refer to this solution or kit as a Vite-comp. It is roughly composed of Vite and three Vite plugins, where each plugin is not coupled with each other and has different responsibilities. In other words, users can get any of the Vite plugins for other applications. Furthermore, open-source applications will be considered like this:
In combination with Vite, React and Rax component development in Vite mode has been implemented. Its advantages compared to the previous component development mode using Webpack are listed below:
Start
Markdown component document with millisecond-level response
TypeScript type recognition
Vite is just getting started. This new compilation mode has already brought me a lot of development benefits. I believe more innovative ideas about Vite will emerge in the future. For example, the frontend integrated solution with a combination of Midway, Lambda, and Vite is stunning. In this thriving frontend era, I believe the combination of Vite with different frontend products will produce wonderful results.
Alan Lu - January 13, 2021
Alibaba Cloud Native Community - December 1, 2023
HaydenLiu - December 5, 2022
Harikrishna - May 24, 2023
Yee - September 9, 2020
Alibaba Cloud Community - October 23, 2024
Explore Web Hosting solutions that can power your personal website or empower your online business.
Learn MoreA low-code development platform to make work easier
Learn MoreExplore how our Web Hosting solutions help small and medium sized companies power their websites and online businesses.
Learn MoreHelp enterprises build high-quality, stable mobile apps
Learn MoreMore Posts by Yee
5916529097415660 August 16, 2021 at 7:04 am
Niubility!!!