Some time ago I decided to make an article that covers topics like publishing to NPM , API architecture. Best tutorial for this would be a react component library development.
A good example of React Component library as for me is react-color. It has neat documentation website with an easy step-by-step guide and lots of different variations of making a color-picker for your React application.
So I decided to go with making a rectangle-popup-menu like Google has:
This is from google.com website (an example of what I plan to make)
Part 1. Preparing project (Setup)
Let’s make up some requirements that every modern library should fit nowadays.
- UMD pattern
- Build output is es5
- Clear documentation
- Examples (demos)
- Unit testing
Rollup & Webpack = Module bundling
Rollup & Webpack
For bundling library, I chose rollup (you can read in a more detailed article that explains why rollup is better for libraries in “Webpack and Rollup: the same but different” by Rich Harris).
Plus I used webpack (and webpack-dev-server) to serve examples folder. It handles css wrapping, font loading and es6 -> es5 transpilation (with the help of Babel).
Jest = Unit testing
Unit-testing tool by Facebook that perfectly fits our needs in comparing react component snapshots.
Express = Serving examples
Has a minor place in a project, but helps us configure proper examples serving properly (as webpack-dev-server is using it).
The sample of code, where we use to express to serve static files for development mode
Babel = write es6, provide es5
In this project, we use Babel mostly for using latest ES features like async/await and supporting JSX subset.
Part 2. Development
Now, once we installed all required devDependencies we are able to move forward with the development process.
The first step is to decide on the project folder structure. For this library, this is what I had at the end:
assets/— Skip this folder, this is just for images I had in API docs
build/— UMD and ES module build files + source maps.
examples/— This folder contains test
.htmlexamples that I use to test library in different cases.
src/— Contains library source code written in JSX and
.babelrcfile for in-folder babel configuration
test/— JEST tests
Other files are needed to complete project configuration. I highly recommend you to use
travis.yml for continuous integration (must-have for modern projects, especially such as a component library).
Important: Don’t forget to exclude
react-domfrom internal dependencies in rollup, otherwise, you’ll get compatibility errors on
the client side and bad side effects, such as large bundle size and bad performance.
Source files / Code
index.js file, I linked every single file that exports classes (actually React components):
We won’t cover all the code written for this library as it’s more topic-specific rather than helpful, so let’s take for example only several parts of the code that explain our needs in project organization.
PopupMenu header part
As we build components for UI we include style files, rollup allows us to make bundles with styles and images the same way as webpack does. In my case I chose
sass syntax as it is a one I am familiar with. This means that
./PopupMenu.scssfile will be compiled from
rollup-plugin-postcss module used in rollup config file
Take into account that we enable
"modules": true feature that enables CSS modules feature:
Any time we use JSX syntax in our ES6 modules we need to include react dependency otherwise, it will result in a build error.
In my case I even need to use React to provide context to child components this old way: (old because recently React introduced new Context API). I have
Popup Table that takes
PopupWidth of the parent
React context in PopupMenu class
I would like to also highlight
classnames npm module that does a pretty good job in combining multiple classes from CSS modules:
classnames module example
First, you need to decide which unit-testing framework you want to choose. There are a few popular unit-testing frameworks I used and could suggest you test:
For this component library, I chose Jest. Because it is developed by Facebook (same as React) and it supports React components snapshot testing out of the box.
Capture snapshots of React trees or other serializable values to simplify testing and to analyze how state changes over time. (From JEST website)
That’s pretty simple, you render a react component you want to test, then call
component.toJSON() which converts it to a rendered html tree. Example:
Once you did it for the first time it is saved into a
*.test.js.snap file, which is basically a module that exports several rendered DOM tree strings to compare with each new render. If the DOM tree has changed, it will tell you that. If the tree was changed by positive changes (means that was expected), you have to run
jest -u to save new snapshots.
Let’s highlight the most relevant tips from this article:
Rollup is better than Webpack for component libraries
Include postcss plugin and bundle css into the same js file
Use Unit testing and continuous integration to show others that you care about stability and prevent unexpected errors.
I would also recommend you divide the build into two steps,
production (Includes minification and further optimizations).
All the sources can be found on Github page. And the resulting demo is available as well.