Unlock the Power of npm: Turn Your React Components into a Library

NPM stands for Node Package Manager. It’s a library and registry for JavaScript software packages. NPM also has command-line tools to help install the different packages and manage their dependencies. They’re open-source and have become the center of JavaScript code sharing. The important point is that it is free to use.

Using NPM makes it possible for us to manage our project dependencies very easily. It defines everything inside the package.json of our project. Running npm install on your project command line will install all the dependencies inside your project. package.json all makes it very easy to manage our project versions.

What is Package.json?

A package.json file is created by your package manager (in this case npm) and exists at the root of a project in JavaScript/Node. To generate a package.json file you can run npm init. You’ll then be asked to fill out some metadata for your project such as:

  • Name – your project’s name.
  • Version – current version in major.minor.patch format (1.0.0, 1.2.3, etc.).
  • Description of the project.
  • License – the license your project is under, so people know how they are allowed to use it.

The package.json file is in JSON format and is used for managing the project’s dependencies, scripts, versions, etc. Here’s a simple example:

{
"name": "My project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "jest",
},
"license": "ISC"
}

What are NPM Scripts?

In the package.json file, there is also a script property. This can be used to run command line tools that are installed within the project’s local context. Common scripts you might use are things like:

  • npm test—to run your tests
  • npm build—to build your project
  • npm start—to run your project locally

Of course, you are flexible to customize scripts that make sense for your specific project.

Related read: How To Create NPM Package For React Native?

Step-by-Step Demonstration

Now below I will give a small demonstration of how you can build and publish your React Components as an NPM library.

Getting Started

To get started, create one React Components project. Open the command line terminal inside the directory where you want to store your project with the create-react-app CLI.

npx create-react-app npm-library-example
# then enter the new directory
cd npm-library-example 
# then start the server 
npm start

Since npx installs the latest versions of react-scripts without installing anything globally, I recommend using it.

npm-library-example/
README.md
node_modules/
package.json public/
Index.html
Favicon.ico
Manifest.json
src/
Index.js
App.js
App.css
Logo.svg
.gitignore
package-lock.json

Your folder structure should look like this.

Now inside the src folder create another folder named button-library.
And inside it create two files and write the following code,

1.button.js

import React from 'react'; // Reusable Button component
function Button({ text, onClick})
{
return (
<button className=”button” onClick={onClick}>
{text}
</button>
);
}
export default Button;

2. style.css

.button {
display: inline-block;
padding: 10px 20px;
font-size: 16px;
background-color: #0074d9;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
}
.button:hover {
background-color: #0056b3;
}
.button:active {
background-color: #003366;
}

Now you can use and test this component inside your App.js.

const handleButtonClick = () => {
alert('Button Clicked!');
};

return (
<div>
<h1>Reusable Button Example</h1>
<Button text="Click Me" onClick={handleButtonClick} className="primary-button" />
</div>
);
}

Now if that works we can move on to the next step.

Initializing the Library

Now open CLI and change your directory to button-library to initialize the package.

cd button-library

To initialize the package run the following command.

npm init -y

This will create a package.json file inside the root directory of your project. It should look like this:

{
"name": "button-library",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

Re-arranging the Package Directory

Now let’s re-arrange our button-library directory so we can use it for bundling.

  • Create a src folder inside the button-library folder and create an index.js file.
  • Now move your button.js and style.css inside the src folder.
  • Your button-library folder should look like this now.
|
- src
| - index.js
| - index.css
| - button.jsx
- package.json

Inside the index.js file write the following code.

import Button from './button.js'

const returnLibrary = () => {
return {
Button: Button
You can also export other components here
}
}
export default returnLibrary()

Install Bundlers

Now let’s install the bundlers. I recommend using rollup since it is very easy to use for bundling libraries as compared to Webpack. You can also use any other bundler you are more exposed to or comfortable with.

Open a command line prompt inside your button-library folder and install the following dependencies.

Note: Make sure to install them as devDependencies by adding the –save-dev flag with your command. Because these dependencies will only be used by you when in development mode if you don’t this will make library users install them if you add them inside the dependencies.

npm install rollup --save-dev

Rollup will be used to compile our code. But since we definitely might want to compile into es5 syntax we shall have to install babel and a plugin to use with rollup. You should not that JSX syntax is special and is not valid in JavaScript so you should also install support for it.

So type the following command int in the command line to install all required packages.

npm install @babel/cli @babel/core @babel/preset-env @babel/preset-react @rollup/plugin-babel --save-dev

Since we are also bundling CSS then we shall have to install a styles bundler for rollup we shall use rollup-plugin-styles.

npm install rollup-plugin-styles autoprefixer --save-dev

We can also install babel runtime helpers. This is important if we are bundling the library with babel.

npm install @babel/runtime
npm install @babel/plugin-transform-runtime --save-dev

If you want source maps then install this plugin too.

npm install rollup-plugin-sourcemaps --save-dev

Get Full-stack React Native Developers to Work on Your Project at Your Convenience!

Configuration

We now need to configure Rollup and Babel so that our code can be compiled.

In the root directory create these two files and write the following code.

1. rollup.config.js

import styles from "rollup-plugin-styles";
import autoprefixer from "autoprefixer";
import babel from "@rollup/plugin-babel";
import sourcemaps from "rollup-plugin-sourcemaps";


// the entry point for the library
const input = "src/index.js";


//
var MODE = [
{
fomart: "cjs", //commonjs
},
{
fomart: "esm", //ECMAScript Modules
},
{
fomart: "umd", //universal module definition
},
];


var config = [];


MODE.map((m) => {
var conf = {
input: input,
output: {
// then name of your package
name: "button-library",
file: `dist/index.${m.fomart}.js`,
format: m.fomart,
exports: "auto",
interop: "auto",
},
// this externelizes react to prevent rollup from compiling it
external: ["react", /@babel\/runtime/],
plugins: [
// these are babel comfigurations
babel({
exclude: "node_modules/**",
plugins: ["@babel/transform-runtime"],
babelHelpers: "runtime",
}),
// this adds sourcemaps
sourcemaps(),
// this adds support for styles
styles({
postcss: {
plugins: [autoprefixer()],
},
}),
],
};
config.push(conf);
});


export default [...config];

2 .babelrc

{
"presets": [
"@babel/preset-react",
"@babel/preset-env"
]
}

Edit Package.json Scripts

Now go to package.json edit the scripts section and change it to this.

"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c"
},

Let’s Build the Package

To create the component build run the following command.

npm run build

This will compile your package into the dist directory.

Edit the Package.json

Your package.json should look like this, It should be different from the previous one when we initialized the package.

Now that our build is ready let’s edit the package.json to make our library ready to publish.

{
"name": "button-library",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c"
},
"license": "ISC",
"devDependencies": {
"@babel/cli": "^7.23.0",
"@babel/core": "^7.23.0",
"@babel/plugin-transform-runtime": "^7.22.15",
"@babel/preset-env": "^7.22.20",
"@babel/preset-react": "^7.22.15",
"@rollup/plugin-babel": "^6.0.3",
"rollup": "^3.29.4",
"rollup-plugin-sourcemaps": "^0.6.3",
"rollup-plugin-styles": "^4.0.0"
},
"dependencies": {
"@babel/runtime": "^7.23.1"
}
}

Change the Main Source of the Package

This is an important step, inside package.json as you can see the main change is to dist/index.cjs.js which is our build file.

Now if you plan to publish this library you can add your name as an author of the package by mentioning your name inside the package.json as an author like this.

author: {
"name":"Ashish Arora",
"email":"ashish.arora@mindbowser.com",
"url":"https://www.mindbowser.com/author/ashish-arora/"
}

Add peerDependencies.

Add peer dependencies like this inside your package.json.

"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}

Publishing

Now we are ready to publish.

For this you need an npm account, so create one if you don’t have one.

Create .npmignore

Your button-library folder should look like this,

|
| - dist
| - index.esm.js
| - index.cjs.js
| - index.umd.js
| - src
| - index.js
| - index.css
| - button.jsx
| - .babelrc
| - package.json
| - rollup.config.js

Since we would not prefer to publish our source code to the npm repository, we only want to publish our compiled code. For this, we need to create a .npmignore file that will prevent unused files from being pushed.

## the src folder
src
.babelrc
rollup.config.js
## node modules folder
node_modules
## incase you have a git repositiory initiated
.git
.gitignore
CVS
.svn
.hg
.lock-wscript
.wafpickle-N
.DS_Store
npm-debug.log
.npmrc


Config.gypi
package-lock.json

Find a Name

Sometimes we might try to create and publish a library with the same name as some other library that is already there on NPM or its name is identical. So it is better to search for a suitable library name before publishing it.

Type and run the following command to search for a name,

npm search [library-name]

If you find that no one is using this name you can go ahead, otherwise, you need to change the name inside the package.json.

Test the Library

To test the library you have to go to other projects on your computer and type.

npm link /path/to/your/library

Adding README.md

The README.md file should contain a description of your package for npm to display. If you’ve ever created a GitHub repository, you’re probably familiar with it.

Publishing

If everything goes well, you can publish it by typing.

npm publish

The above demonstration could introduce you to a few new concepts or things you’re not familiar with. So below I have tried to clear the confusion for you with a summary of those concepts.

Dependencies vs devDependencies vs peerDependencies

  1. Dependencies are the list of modules/packages that are required for your project to run. These are installed using npm install to add the package to the dependencies list.
  2. devDependencies, short for development dependencies, are modules/packages that are NOT required for your project to run. These are often things that help the development process but aren’t part of the project themselves. For example, linters like eslint, testing, etc.
  3. A peer dependency specifies that our package is compatible with a particular version of an npm package. If a package doesn’t already exist in the node_modules directory, then it is automatically added. As you install a package, npm will automatically install the dev dependencies.

Semantic Versioning (1.2.3)

  1. Major – A MAJOR version involves breaking changes—likely you will need to update the package in your project when a major version has changed.
  2. Minor – A MINOR version change is backward compatible, meaning it should update without breaking things (well, one can hope).
  3. Patch – A PATCH version change is backward compatible with bug fixes or other small fixes.

Advantages

Above I have explained almost everything, but why you need to start developing and publishing your libraries so below are some examples.

  1. Code reusability and consistency between multiple projects.
  2. Speed up development.
  3. Encourage collaboration between developers.
  4. Eases Maintenance.
  5. Simplifies deployment.
coma

Conclusion

This guide walks you through using npm to turn your React Components into a reusable library. It covers npm basics, managing dependencies, and publishing your library. By following these steps, you can streamline your development process, promote code sharing, and simplify deployment. Embracing npm empowers you to collaborate effectively and enhance your development workflow.

Keep Reading

Keep Reading

  • Service
  • Career
  • Let's create something together!

  • We’re looking for the best. Are you in?