How To Publish a React Component Library
Now that you’ve built something useful, share it with the world
- GitHub repo: https://github.com/leon0707/demo-component
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.
- In the
DemoComponent
, it imports CSS and image files, and uses other React libraries. - 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
andcss-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:
- Remove
react.production.min.js
from the bundle file. - 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>
.