React was recently used to encapsulate a component library for daily business needs. Due to space reasons, only the selection and packaging of the development process is discussed here, and the packaging of specific components will be discussed later.


The article was first published
Personal blog

An overview of the

As we all know, componentized development pattern for our development has a great efficiency increases, the fundamental component of our everyday use for encapsulation, can simplify a lot of our attention for basic UI, let our work focus on business logic, good separation business and the basis of the UI code, make the whole project more toning, This is why we want to develop this component library.

However, there are many existing React open source components, such as Ant-Design and Material – UI, etc., so it is always necessary to consider whether it is necessary to spend energy to build a component library suitable for your team. Let’s take a look at some characteristics of my current team and business:

  1. There are a lot of people at the front end, they need to cooperate with each other, and they have the power to develop the components
  2. Product services are relatively complex, and some components need to be customized
  3. There are mature design specifications that define the various base components, base styles, and so on
  4. The current project is messy, with references to third-party components

As you can see, we have the energy and foundation to encapsulate our own components, and the need to change the current state of development with basic component encapsulation. So, this is something that we should and need to do as soon as possible.

Technology selection

For the package of component library, we first face the selection of technology and plan. It probably includes the following two points:

  • The most basic technical scheme
  • Develop processes and specifications

Technical scheme selection

Webpack + React + Sass

Since the team’s existing projects are all developed based on React+Redux, React was definitely the development language we chose.

SASS

For CSS options, although modular solutions such as CSS Modules and CSS-in-JS are popular for componentized development, we prefer our components to be customizable. Therefore, for components, we use Sass as a precompiled language to improve efficiency and standardization. With CSS-Modules, it’s easy to make style changes to suit your needs. For example, if we have a Tab component, we have defined its general style:

.tip-tab { border: 1px solid #ccc; } .tip-tab-item { border: 1px solid #ccc; &.active { border-color: red; }}Copy the code

In business, we need to fine-tune the style of the Tab component for a specific requirement. Make the border color blue when it is in the active state. You could certainly say that we could expose some props for our component, configure for those changes, and pass in different props for different styles. But we often can’t meet all business requirements and encapsulate all styles for components. For this scenario, we use CSS-modules to add a unique module style:

<Tab styleName="unique-tab" />Copy the code

For this module, modify its basic style:

.unique-tab { :global { .tip-tab-item { border-color: #eee; &.active { border-color: blue; }}}}Copy the code

In this way, the custom style for the module can be well customized for the needs of the style, while not polluting the global style.

Icon

For project ICONS, the SVG-Sprite scheme is planned. But because the product is in an iterative process, new ICONS are constantly added. Currently we do not package ICONS uniformly, but import all ICONS from the project each time a component is packaged. Introduce in the following way:

import Icon from '@common/lib'
import errorIcon from '@images/error.svg'

<Icon link={errorIcon} />Copy the code

A better way would be to pack all ICONS uniformly and generate an SVG-spirte file (see SVG-Sprite for details). When we use it, we just reference it directly, avoiding packaging every time and reducing the time webPack handles dependencies:

<Icon type="error" />Copy the code

Develop processes and specifications

For development processes and specifications, we follow the following principles:

  • The component library is developed completely independently of the project to facilitate the use of multiple subsequent projects
  • The component library consists of three modes: development, test, package, document case, and distinguish between different entries and states
  • Use pure-renderautobind, etc. to ensure the performance and efficiency of components as much as possible
  • Ensure the semantics of props and callbacks. For example, callbacks are handled by handleXXX

In order to facilitate subsequent extensions, we prefer to develop the entire component library completely separate from the project. Ensure that the component library encapsulates only the most basic components, separating project UI code from business logic.

We have different file entries for different modes. For development mode, we start a dev-server, which basically encapsulates and debugs components. When packaging, we simply encapsulate the component content to expose a unified interface. In the documentation, we need to present cases and illustrations. So we are using webpack features to configure various environments:

NPM run dev NPM run test NPM run build NPM run styleGuide NPM run styleGuide NPM run dev NPM run testCopy the code

Component library as the minimum strength support of the project, we need to ensure its basic rendering efficiency, so we use pure-render/autobind and other basic optimization. React has a number of optimizations that I won’t go into here.

packaging

basis

For the packaging of the component library, we packaged it in UMD format. Webpack can format the output :(quoted from cnode)

  • Var is output as a variable
  • “This” outputs an attribute of this: this[” Library “] = XXX;
  • “Commonjs” exports as a property of exports: exports[” Library “] = XXX;
  • Commonjs2: module. Exports = module. Exports = XXX;
  • “Amd” is output in AMD format.
  • “Umd” is output as AMD, CommonJS2, and global attributes.

The configuration is as follows:

output: {
  path: config.build.assetsRoot,
  filename: utils.assetsPath('js/[name].js'),
  chunkFilename: utils.assetsPath('js/[id].js'),
  library: 'TipUi',
  libraryTarget: 'umd'
}Copy the code

Rely on

It is obvious that we are encapsulating a library of components for React and should not reference React. Generally, we can use externals to process it.

Here, we package it with other third party dependencies in DLL mode, and export manifest.json and the output file of the third party dependencies to the project, and use dllReference in the project. Avoid repeated packaging when using these dependencies in your project.

Also, because our component library is in a state of constant maintenance. This requires us to maintain a good packaging relationship between the project library and the project. The specific process is shown in the figure:

In each project packaging, first check whether the UI library has been updated, if not, then directly package. On the contrary, continue to detect whether the DLL dependency changes, if so, then package DLL, otherwise directly package component library content. The output is then synchronized to the project before final packaging.

Of course, all of these processes are automated.

Documentation and Examples

A well-documented component library is extremely important, what configuration parameters each component has, what event callbacks it has, and the corresponding Demo and presentation effects. Assuming that without this, no one knows how to use it except the person who encapsulates the component. However, the process of writing documents is often painful. Here are some document generation libraries that can greatly simplify the document work:

  • Docsify is a Vue based component generator that is lightweight and easy to use
  • React-styleguidist React-based component library document generator, which automatically generates documents based on comments and supports Demo demonstration. Super handy
  • Bisheng Ant Design’s own document generator

We use StyleGuidist, which can automatically convert MD to documentation, and can directly call your packaged components in MD and display them. It is easy to use. The final packaged document looks something like this:

conclusion

In fact, the package component library has a lot of things worth pondering and study, due to space reasons, here only on the development process of the more tangled selection and packaging are discussed, and then on the specific components of the package. You can learn a lot by constantly referring to ant Design, an excellent component library, as you write. A deeper understanding of the idea of encapsulating components is a good process.