How To Publish a React Component Library

Now that you’ve built something useful, share it with the world

Leon Feng
Better Programming

--

You have created a very useful component in your React project. You want to share it with the open-source world and, hopefully, it helps other fellow developers.

The most common way is to publish it to npm where JavaScript developers can easily download JS libraries and import them into their projects.

This article will demonstrate how to do it step-by-step, and highlight potential problems you may encounter.

Let’s create a more complicated scenario so that it is closer to a real-world project.

  1. In the DemoComponent, it imports CSS and image files, and uses other React libraries.
  2. When using Babel to compile the React component, you don’t want to compile it with all dependencies like React, react-dom into it. Not only will it increase the size of the package, but also having multiple copies of React will cause errors.

First of All, Create a React Component Project

Create the project directory on a local dev environment and a repository on GitHub.com.

mkdir react-democomponent
cd react-democomponent
mkdir src
npm init

It is OK to use default values to create the package.json file. Those values will be changed in the future.

The directory will look like this:

/react-democomponent
--- /src
--- .gitignore
--- LICENSE
--- package.json
--- README.md

This will be a React project, so we need to install React and prop-types first.

npm install --save-dev react prop-types

Select a component you’ve created or copy the demo component and move them into the src folder.

The DemoComponent has three parts:

  • The React component itself.
  • The style file.
  • An SVG image file.

The goal is to create one JS file which includes all of them, so it can be imported in other React projects.

This component is simple, and will look like a download button.

Step 2. Compile the Component

Some browsers will not understand the latest ECMAScript and React JSX syntax, so it is necessary to convert ES6, ES7, ES8 code or JSX to a JavaScript code in a backward-compatible version. Babel will do this.

Install Babel dependencies and create a Babel configuration file.

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

.babelrc file.

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

@babel/preset-env will convert all code that utilizes the latest JavaScript features into the code that is compatible with browsers that don’t support the latest JavaScript features.

This plugin can also make bundle files smaller. Developers can specify the min versions of browsers with which the code is compatible. More details: Babel docs.

@babel/preset-react will convert the latest JSX to JavaScript code. More details: Babel docs.

In the DemoComponent, a class property handleOnClick is created. The class property is still an experimental feature, and is not supported yet. To make it work in the component, you have to add a Babel plugin.

npm install --save-dev @babel/plugin-proposal-class-properties

Add "plugins": ["@babel/plugin-proposal-class-properties"] to the .babelrc file.

An error will be thrown if the plugin is not enabled:

ERROR in ./src/DemoComponent.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: Support for the experimental syntax ‘classProperties’ isn’t currently enabled.

webpack is a static module bundler for modern JavaScript applications. All we need to do is to create a webpack configuration file.

Install webpack and the webpack CLI tool.

npm install --save-dev webpack webpack-cli

webpack.config.js

  • The entry object is where webpack looks to start building the bundle.
  • The output object tells webpack where to emit the bundles it creates and how to name these files.
  • The loader allows webpack to process other types of files and convert them into valid modules that can be consumed by your application and added to the dependency graph.

In this project, four loaders have been used:

  • babel-loader transpiles JavaScript files.
  • style-loader and css-loader load and inject CSS style sheets into the DOM.
  • url-loader transforms files into base64 URIs.

These packages need to be installed.

npm install --save-dev babel-loader style-loader css-loader url-loader

Add build in the package.json.

...
"scripts": {
"build": "webpack --mode production --display-modules"
},
...

Build the Bundle

Now you can build the bundle.

Run npm run-script build, main.js has been created under dist. This is the file that will be distributed on the npm registry where other people can search and download it.

This is the log:

Hash: 869e38eb4f7cf4851eb0
Version: webpack 4.41.5
Time: 1613ms
Built at: 01/07/2020 7:59:49 PM
Asset Size Chunks Chunk Names
main.js 18.8 KiB 0 [emitted] main
Entrypoint main = main.js
[0] ./node_modules/react/index.js 190 bytes {0} [built]
[1] ./node_modules/prop-types/index.js 710 bytes {0} [built]
[2] ./node_modules/react/cjs/react.production.min.js 6.49 KiB {0} [built]
[3] ./node_modules/object-assign/index.js 2.06 KiB {0} [built]
[4] ./node_modules/prop-types/factoryWithThrowingShims.js 1.58 KiB {0} [built]
[5] ./node_modules/prop-types/lib/ReactPropTypesSecret.js 314 bytes {0} [built]
[6] ./src/DemoComponent.css 580 bytes {0} [built]
[7] ./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js 5.83 KiB {0} [built]
[8] ./node_modules/css-loader/dist/cjs.js!./src/DemoComponent.css 276 bytes {0} [built]
[9] ./node_modules/css-loader/dist/runtime/api.js 2.04 KiB {0} [built]
[10] ./src/DemoComponent.js + 1 modules 8.11 KiB {0} [built]
| ./src/DemoComponent.js 3.32 KiB [built]
| ./src/logo.png 4.77 KiB [built]

Step 3. Test It Locally

It is straightforward. You need to import this React component and use it in your React project.

Update the package.json file, add meaningful information into it.

Replace the values with your own information. Note that the main should point to the JS file that was built.

Run npm link to create a symlink in the global folder that links to this package.

To import this package into your React project, you need to go to the directory of the React project and run npm link react-download-button or the name in the package.json.

Import the package.

import DemoComponent from 'react-download-button';

At this moment, an error will be thrown, because there are two React instances. One is in your React project, and another one is in the package you created.

Error: Minified React error #321

This is true. If you check the building log or open the main.js in the editor, you can find react.production.min.js.

The solve this problem, you need to:

  1. Remove react.production.min.js from the bundle file.
  2. Tell webpack of the React project which React instance you want to use.

Step 1

Check the building log, there are some packages that should not be included in the bundle file. They increase the size of the bundle and cause unnecessary problems.

react, prop-types, for example, should not be included. You can exclude them or other packages easily by adding webpacke-node-externals.

npm install --save webpacke-node-externals

Update webpack.config.js in the package.

const nodeExternals = require('webpack-node-externals');module.exports = {
...
target: 'node',
externals: [nodeExternals()]
}

Run npm run-script build to rebuild the bundle file. This time, it won’t have react and props-types in the file anymore. However, the React project should have them, and these need to be specified in the package.json.

"peerDependencies": {
"react": "^16.12.0",
"prop-types": "^15.7.2"
}

Step 2

In the React project file, update the webpack configuration file.

  "resolve" = {
alias: {
react: path.resolve('./node_modules/react')
}
}

This will tell webpack to use local React, not the React in the DemoComponent directory.

Now the package your created can be used in any React project.

Step 4. Publish It on npm

It is recommended to have a helpful README file to demonstrate how to use your package and details you want other developers to know.

Once you think everything looks perfect, go to https://www.npmjs.com/ to sign up and verify the email.

Then, go to the package directory to run npm login and npm publish.

End

You should be able to see that your package is published on npmjs.com, and it can be downloaded by running npm install <package name>.

--

--