How to Build a React component library?

alirezace

Alireza

Posted on January 12, 2023

How to Build a React component library?

In this article I tried to talk the steps of create a react component library.

Why do we need to build a react component library?

If you have several components that are shared between your projects or some js code that is copy-pasting and these things happen more than 2 or 3 times then you need to convert your shared code to a library.

So let's create a react component library.

First, we need to generate our component. We can create a React project and create a component. Our folder structure would be like this:

├── src
│   ├── components
|   │   ├── Button
|   |   │   ├── Button.tsx
|   |   │   ├── Button.scss
|   |   │   └── index.ts
|   │   ├── TextField
|   |   │   ├── TextField.tsx
|   |   │   ├── TextField.scss
|   |   │   └── index.ts
|   │   └── index.ts
├── package.json
├── tsconfig.json
└── rollup.config.js
Enter fullscreen mode Exit fullscreen mode

src/components/index.ts

export { default as Button } from "./Button";
export { default as TextField } from "./TextField";
Enter fullscreen mode Exit fullscreen mode

After we create our component we need to config our rollup. We use rollup to bundle our library(also we could use webpack).

Let's config our rollup to bundle our library:

rollup.config.js

import externalDeps from 'rollup-plugin-peer-deps-external';
import typescript from '@rollup/plugin-typescript';
import sourcemaps from 'rollup-plugin-sourcemaps';
import resolve from '@rollup/plugin-node-resolve';
import commonJS from 'rollup-plugin-commonjs';
import replace from '@rollup/plugin-replace';
import styles from 'rollup-plugin-styles';
import babel from 'rollup-plugin-babel';
import json from '@rollup/plugin-json';
import pkg from './package.json';

const globals = {
  react: 'React',
  'react-dom': 'ReactDOM',
  'react-query': 'ReactQuery',
};

const plugins = [
  externalDeps(), //prevents packages listed in peerDependencies from being bundled with our component library
  commonJS(), //convert common js modules to es6
  resolve(), // Locate and bundle third-party dependencies in node_modules
  typescript(), // transpiles our TypeScript code into JavaScript.
postcss() // transforms our Sass into CSS
];

export default {
  input: `./src/components/index.ts`,
  output: [
    {
      name: 'index',
      file: `lib/index.cj.js`,
      format: 'cjs',
      sourcemap: true,
    },
    {
      name: 'index' ,
      file: `lib/index.es.js`,
      format: 'esm',
      sourcemap: true,
    },
    {
      name: 'index',
      file: `lib/index.umd.js`,
      format: 'umd',
      sourcemap: true,
      globals,
    },
  ],
  plugins,
}));
Enter fullscreen mode Exit fullscreen mode

esm vs common js vs umd
These types are js module formats.
Some tools like webpack and node use common js format and some tools like rollup and webpack2 use esm module. umd(Universal Module Definition) is the type of module that strive to work everywhere. Also, umd is a kind of fallback for other formats. If you want to include any of these files in the browser as standalone script tags without a build step like e.g. Webpack, you will want to use umd.

How to test our packages?
we have 3 options to test our package before publishing:

  1. npm link
  2. npm pack
  3. Storybook

npm link:
npm link add our package in node_module universal of your system and install your package globally. every time we change our files this package will be updated in node_modules folder.

npm pack:
This command will pack our package and we can install the package in our project. with every change that we make in our package, we need to run this command and install our library again.

Storybook:
In my opinion, the best way to test our package locally is Storybook.
In addition, to test our package, we can also have good documentation.

Final step:
Finally, we should publish our package.
with npm publish we can publish our package in the npm registry but before that, we should create an account in npm.
also, we need to make some changes in our packge.json file.

package.json:

{
  "name": "@react-components-library/react-sample-components-library",
  "version": "0.0.20",
  "main": "lib/index.js", // common js 
  "module": "lib/index.es.js", //esm
  "browser": "lib/index.umd.js", //umd
  "files": [
    "/lib"
  ],
  "type": "module",
  "scripts": {
    "test": "jest",
    "start": "styleguidist server",
    "build": "rm -rf ./lib && rollup -c",
    "prepublishOnly": "rm -rf lib && npm run build",
    "postbuild": "npm pack && tar -xvzf *.tgz && rm -rf package *.tgz",
    "docs:build": "styleguidist build"
  },
  "peerDependencies": {
    "react": "17.0.2",
    "react-dom": "17.0.2"
  },
...
}
Enter fullscreen mode Exit fullscreen mode

There are some tips here:

  1. we should our react and react-dom in our peerDependencies to prevent rollup to add these packages in our bundle.
  2. when npm publish execute, first run prepublishOnly script. so we can add our build steps to this script.
  3. files indicates which files or folders should push to the npm registry.
💖 💪 🙅 🚩
alirezace
Alireza

Posted on January 12, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related