https://github.com/sasha240100/react-rectangle-popup-menu
Originally published at ZeoLearn.
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 easy step-by-step guide and lots of different variations of making a color-picker for your React application.
https://casesandberg.github.io/react-color/
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)
Let’s make up some requirements that every modern library should fit nowadays.
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).
Rollup: https://rollupjs.org/guide/en
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).
Webpack: https://webpack.js.org/
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).
Babel = write es6, provide es5
Nowadays ES6 is already widely supported by a majority of well-known browsers, but Babel is not just about working with es5, it’s a global standard for transpiling javascript subsets into browser-compatible implementation.
In this project we use Babel mostly for using latest ES features like async/await and supporting JSX subset.
Link: https://babeljs.io/
Now, once we installed all required devDependencies we are able to move forward to 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 docsbuild/
— UMD and ES module build files + sourcemaps.
examples/
— This folder contains test .html
examples that I use to test library in different cases.src/
— Contains library source code written in JSX and .babelrc
file for in-folder babel configurationtest/
— JEST testsOther 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
andreact-dom
from 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.
// rollup.config.babel.js{
// ...external: ['react', 'react-dom'],
globals: {react: 'React','react-dom': 'ReactDOM'}}
In the index.js
file I linked every single file that exports classes (actually React components):
// index.jsexport * from './PopupMenu';export * from './PopupTable';export * from './PopupText';
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.
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.scss
file will be compiled from sass
to css
and then included as a javascript code that inserts inline styles into html <head>
tag.
Take into account that we enable "modules": true
feature that enables CSS modules feature:
import style from './PopupMenu.scss';
// Somewhere in JSX// ...
render() {return (<div className={style.myClassName} />)}
// ...
Any time we use JSX syntax in our ES6 modules we need to include react dependency, otherwise it will result in a build error.
import React, {Component} from 'react';
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 PopupTable
that takes popupWidth
of the parent PopupMenu
I would like to also highlight classnames
npm module that does pretty good job in combining multiple classes from CSS modules:
classnames module example
Usage:
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 to 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:
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`PopupMenu should render correctly 1`] = `<divclassName="PopupMenu_PopupMenu__8TfA4"><divclassName="PopupMenu_button__20m_Y"onMouseOut={[Function]}onMouseOver={[Function]}/><divclassName="PopupMenu_popover__3hd_Z"onMouseOut={[Function]}onMouseOver={[Function]}style={Object {"height": "auto","left": "calc(-100px + 50%)","visibility": "hidden","width": "calc(200px - 10px)",}}/></div>`;
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:
I would also recommend you divide the build into two steps, development
and **production**
(Includes minification and further optimizations).
All the sources can be found on Github page. And the resulting demo is available as well.
Originally published at ZeoLearn.
Recently I’ve made an “Introduction into WebGL world” course for Skillshare, you may find some interesting webgl secrets there! click here.