This is a competing research article that I don't know what the title is. Recently, I have investigated several excellent foreign open source component libraries. One is to make a basic component library for technical reserves in the future, and the other is to jump out of the "comfort zone" of domestic antd and see how foreign teams are doing for component libraries. Designed.
written summary
In order to make it easier for everyone to see the conclusion directly, here I have moved the conclusion that was originally written at the end of the intranet to the beginning. (Because from the intranet, people don't really want to see how I analyze the source code, but just want to see the conclusion and what I will do...)
Architecture implementation
From the perspective of code structure, it can be roughly divided into the following categories:
- Single package and multiple components: Represented by antd, all components have a unified version;
- Multi-package and multi-component: Most of the foreign component libraries adopt this structure, each component wants to have a separate version, and the major version is consistent;
component granularity
In terms of component granularity, it can be roughly divided into the following categories:
- Coarse granularity: Take antd Modal as an example, the custom rendering slot of this type of component is provided in the form of render props;
- Fine-grained: Take most of the components of Radix-ui as an example, such components are provided in the form of container + children sub-components, which advocates the free combination of sub-components and is highly flexible;
- Finer granularity: Take React-Spectrum components as an example. Such components are not only provided in a fine-grained form at the UI layer, but also logically split into finer-grained logic hooks;
style system design
From the perspective of style system design, it can be roughly divided into the following categories:
- No style system: Take rc and headless ui as examples, such component libraries do not provide any style files, and are all implemented externally by the business side;
Has its own design language:
- Style file: Taking antd as an example, the style of this type of component library is provided to the component in the form of an external style file, and the user can override the style externally through className and style;
- StyledComponents: Take Chakra-ui as an example, the style of this type of component library is built into the component in the form of css in js, and the user can override the style by customizing the theme and className;
My point of view
In fact, when I read the implementation of Charkra-ui, I already had a rough design of the basic component library in my heart.
First of all, from the perspective of the style system, one of the purpose of re-creating the component library is to avoid style pollution. So, assuming that the design language has been unified, can we radically use the form of css in js to write our components?
Next, in terms of the structure of components, students who have done business components may know that business components are simply a combination of basic components for a certain scenario, and only one or a few of the basic components are often used in the combination process. function (even disgusting castration rewriting when it is not satisfied), then when designing basic components, can you design more atomic basic components that are already atomic? (such as those basic components currently abroad)
So here comes the challenge:
- Does a more atomic design mean that the user needs to write more combinational logic in the business code?
- Does the design that is incompatible with antd api mean that the users of the stock business eat shit-like compatible migration costs?
- ...
However, I have come up with a solution. For some of the above problems, can we design an adaptation layer to smooth out the api difference between the new component and antd? The adaptation layer encapsulates a layer of "skin" according to antd's api "Come and go for the stock business to use.
Then according to this design, is our component library architecture like this:
First of all, for the business component library, the bottom layer is all reconstructed with new basic components, and the original api is not changed externally. For the user of the business component library, there is no perception. For stock business, lock the specified version of antd api, and provide an adaptation layer compatible with antd api for smooth transition. For incremental business, it is recommended to directly use the basic component library for development. (Of course I don't know about using the adaptation layer...)
(The above is just my personal opinion...)
List of component libraries written in the back
Ant-Design
- Repository: https://github.com/ant-design/ant-design
- Official website: https://ant.design/index-cn
Architecture pattern: UI implementation (antd) + headless implementation (rc)
- UI implementation: single warehouse, single package, multiple components, each component encapsulates UI and events based on headless components, and introduces headless components according to the specified version;
- Headless implementation: multi-warehouse, single package, single component, MutiRepo, no style, only dom and logic are implemented;
The biggest feature of antd is the separation of UI and dom + logic. For custom rendering scenes in components, most of them exist in the form of components + render props. Take Modal as an example:
On the style system, what antd brings to us is the most common component with a styleless file.
Chakra-ui
- Repository: https://github.com/chakra-ui/chakra-ui
- Official website: https://chakra-ui.com/
- Architecture mode: single warehouse, multi-package, multi-component, MonoRepo;
In the implementation of Charkra-ui, there is not much difference between the basic ui components such as Input and Select and the conventional component library. For components with more custom rendering scenes such as Modal, Tooltip, and Popover, pluggable sub-components are used. Implemented in the form of component composition, such as Modal:
In terms of implementation, Modal does not serve as the ui component that actually mounts the dom, but distributes props as the container layer (implemented through context), while the part that actually renders the UI is carried by sub-components, and each sub-component receives the container layer as an entity. The dispatched props handle the corresponding ui display and events, taking ModalCloseButton as an example:
Charkra-ui is also interesting in the design of the style system. First of all, in the use of css, Charkra-ui adopts StyledComponents based on @emotion/styled . In the implementation of the component, each native dom element or other component is converted into StyledComponents through the factory function under the subpackage @chakra-ui/system. Here is an example of Input:
For the basic styles required by StyledComponents, Charkra-ui provides the theme subpackage as the default style theme of the component library. The theme package defines the styles required by each component in the form of JS objects.
Then, in order to inject the default theme and custom theme into the component, Charkra-ui provides a Provider to inject theme styles
The use of StyleComponents also makes it impossible for us to reasonably override the styles in the components from the outside. Charkra-ui also provides us with className props.
MUI
- Repository: https://github.com/mui/material-ui
- Official website: https://mui.com/zh/
- Architecture mode: single warehouse, single package, multiple components;
The implementation of components is very similar to Charkra-ui, and the StyledComponents based on @emotion/styled are also used in the style system.
headless-ui
- Repository: https://github.com/tailwindlabs/headlessui
- Official website: https://headlessui.dev/
- Architecture mode: single warehouse, single package, multiple components;
Headless-ui is actually equivalent to the react-component (rc) that antd depends on. It only cares about dom + logic implementation, and the UI style implementation is handed over to the user;
Radix-ui
- Repository: https://github.com/radix-ui/primitives
- Official website: https://www.radix-ui.com/
- Architecture mode: single warehouse, multiple packages and multiple components, MonoRepo;
Compared with Charka-ui, Radix-ui also adopts the form of pluggable sub-components in Select, the most basic data response component. That is to say, in the implementation of Radix-ui, the granularity of sub-components is lighter and more atomic. , take Select as an example:
In terms of implementation, the container layer is also used to collect props through the context, and subcomponents are used as UI to respond to the props dispatched by the container layer.
Likewise, Radix-ui advocates a styleless component library.
React-Spectrum
- Repository: https://github.com/tailwindlabs/headlessui
- Official website: https://react-spectrum.adobe.com/index.html
- Architecture mode: single warehouse, multi-package, multi-component, MonoRepo;
React-Spectrum consists of three parts in implementation:
- React-Aria: Separating and providing reusable logic such as component behavior, accessibility, and internationalization in the form of hooks;
- React-Stately: Split part of the state used inside the component out of hooks for logical reuse;
- React-Spectrum: Combines React-Aria, React-Stately, and DOM to implement basic components;
Compared with the above component libraries, React-Spectrum not only splits components from the UI side in the form of sub-components in a fine-grained manner, but also splits React-Aria and React-Spectrum on the logic side to provide hooks to achieve logical splitting and decoupling . In the same way, decoupling of subcomponents is also implemented in the form of context.
On the style system, React-Spectrum does not recommend that users implement the logic of overriding styles through classNames or styles, so we cannot see these two props on components. React-Spectrum believes that due to style overrides, subsequent component upgrades will bring about Unforeseen problems.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。