Build a React Component Library

Hinam Mehra
5 min readJul 1, 2020

I have always liked the idea of building code as lego-blocks — re-usable, modular, simple on their own but capable of great things when they come together.

In this 4-part series, we are going to focus on building a shared Auth Component Library that can be (privately) published and consumed by your entire team.

Photo by HONG LIN on Unsplash

Thoughts on create-react-library?

I tried it, I spent a week trying to figure it out and although a great package to start trying this idea out, I felt like it was a truck compared to the sports car I wanted and it really slowed down development (I couldn’t use the shorthand for fragments for some reason!). Plus, it’s not being actively maintained anymore which was a hard pass for me.

Github

If you’d like to skip to the end, here’s the github-repo:

Objective

In this tutorial, we are just going to set-up the foundations of our component library with a HelloWorld component.

1. Setting up the project

In a directory of your choice, create a simple react app:

$ npx create-react-app auth-component-library

2. Create a HelloWorld Component

  1. Create a src/components folder and create a HelloWorld.js file inside it.(Optional: delete the public folder and all the other files inside the src folder)

2. Create an index.js file inside the src folder and export the component we just created. index.js file will be our key file throughout this process, exporting all the components we will create inside the components folder.

5. The folder structure should now look like this:

..
-- src/
|-- components/
|-- HelloWorld.js
|-- index.js
-- package.json

3. Configure Rollup.js & Babel to Build Our Library

We have the first component of our library good to go. Now, to build our library, we need to install Rollup.js, Babel and other packages we require to bundle our library.

  1. We will be installing the following packages:
$ cd auth-component-library$ npm i -D @babel/cli @babel/core @babel/preset-env @babel/preset-react rollup @rollup/plugin-babel rollup-plugin-delete rollup-plugin-peer-deps-external npm-run-all

2. Next, create a .babelrc file in the root folder. It should look like this:

.babelrc in the root folder

3. Next, create a rollup.config.js file in the root folder. It should look like this:

rollup.config.js in the root folder

This is what each configuration field stands for:

  • input: The entry point to the component(s) we want to bundle. We directly point this to our src/index.js which we have used to export our components.
  • output: This specifies the directory where you want to save the bundled library. We are importing the output paths from package.json (More about this in the next step), which we will specify as the ./dist folder.
  • plugins: This specifies all the plugins you wish to use and their respective configurations. For instance, external is asking rollup to exclude peerDependencies as part of the bundle as they will be imported separately by the app calling this package. We will also configure peerDependencies in the next step.

The folder structure at the end of this step should look like this:

-- src/
|-- components/
|-- HelloWorld.js
|-- index.js
-- .babelrc
-- rollup.config.js
-- package.json

4. Configure package.json

  1. Add source, main & module values in package.json for our rollup.config.js
{
"name": "auth-component-library",
"version": "0.1.0",
"private": true,
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"source": "src/index.js",
...
}

2. Add react, react-dom to peerDependencies and remove them from dependencies .

{    "dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"react-scripts": "3.4.3"
},
"devDependencies": {
"@babel/cli": "^7.10.5",
"@babel/core": "^7.11.4",
"@babel/preset-env": "^7.11.0",
"@babel/preset-react": "^7.10.4",
"@rollup/plugin-babel": "^5.2.0",
"rollup": "^2.26.4",
"rollup-plugin-delete": "^2.0.0",
"rollup-plugin-peer-deps-external": "^2.2.3"
},
"peerDependencies": {
"react": "^16.13.1",
"react-dom": "^16.13.1"

},
}

3. Add scripts (to make our lives a bit easier)

Lastly, we need to add two scripts to our package.json which will compile the components into a bundle using the configurations in rollup.config.js . Don’t worry about the playground scripts, just add them, they’ll make more sense in the next step when we set up our “Testing Playground”.

{
...
"scripts": {
"build": "rollup -c",
"build-watch": "rollup -c -w",
"start-playground": "cd playground && npm run start",
"i-all": "npm i && cd playground && npm i",
"dev": "npm-run-all --parallel build-watch start-playground"
},
...
}

4. The new package.json should look like this:

Version 2: package.json

5. Let’s build our library!

Now, run the following commands:

$ npm update && npm run build

You should have a ./dist folder with two bundled files in it, index.cs.js and index.esm.js

You have successfully created a component library! Now, we build our Testing Playground.

5. Add a Testing Playground to Our Project

We are now going to create a “playground” in our app so we can test our components as we develop them.

  1. For this, we are going to create another react app, this time inside the app we have already created.
$ cd auth-component-library
$ npx create-react-app playground

2. Add the auth component library you just created as a dependency in playground/package.json . Also make sure to link react and react-dom to the already installed packages. Without this, it will give you “Invalid Hook Call” error when we start adding more complex components.

{
"name": "playground",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"auth-component-library": "file:..",
"react": "file:../node_modules/react",
"react-dom": "file:../node_modules/react",
"react-scripts": "file:../node_modules/react-scripts"

},
...
}

3. Modify playground/src/App.js to call the <HelloWorld /> component

playground/src/App.js

4. Run the playground app:

$ npm run i-all
$ npm run dev

This will build our library, watch for modifications, and run the Playground App at http://localhost:3000 . You should now see “Hello World” on your screen in giant letters. It’s a small but meaningful victory!

You can also modify the <HelloWorld /> component and your screen should update automatically.

Next Steps:

  • In Part II, we publish our shared component library in a private Github Respository so it can be easily shared across the team.
  • In Part III, we add complex Material UI components to our library, such as fully-functional<SignIn /> component.
  • In Part IV, we add a mock JSON-API to our playground, to make sure our components will consume production Rest APIs properly.

--

--