Let’s create a reusable react library and publish it as an NPM package to use across multiple projects. Components in React are the perfect way to do this.
I will build this UI following a Component-Driven Development(CDD) methodology.
Here at icddr,b, we use the create-react-app (CRA) toolchain for our React projects. The benefit of CRA is it sets up our development environment so that we can use the latest feature.
To create the project, run (Here, I used yarn as the package manager. I will not dive into the installation procedure of node or yarn):
yarn create react-app react-components
cd react-components
Now that we have our project created, let’s add the Storybook to the project and start building our segregated components.
I will set up the Storybook using the below automated command-line tool. This command adds a set of boilerplates for Storybook.
npx -p @storybook/cli sb init
yarn storybook
Before starting the project, add below in the package.json file and run ‘yarn install’.
"resolutions": {
"babel-loader": "8.1.0"
}
yarn install
Now run the project.
yarn start
yarn storybook
By default, the storybook adds examples in the stories folder (src/stories
). In this tutorial, I will not follow this convention rather rely on the .stories.js
naming scheme.
To adopt the different conventions, we can easily change the storybook configuration files which reside in ./storybook/main.js
.
I will delete the /stories
directory for this tutorial.
I will create a simple button component and its story file. src/components/Button.js
and src/components/Button.stories.js
//Button.js
import React from 'react';
import PropTypes from 'prop-types';
export default function Button({ label, backgroundColor, onClick }) {
return (
<button onClick={onClick}
style={backgroundColor && { backgroundColor }}>
{label}
</button>
);
}
Button.propTypes = {
backgroundColor: PropTypes.string,
label: PropTypes.string.isRequired,
onClick: PropTypes.func,
};
Button.defaultProps = {
backgroundColor: null,
onClick: undefined,
};
// Button.stories.js
import React from 'react';
import Button from './Button';
export default {
title: 'Example/Button',
component: Button,
argTypes: {
backgroundColor: { control: 'color' },
},
};
const Template = (args) => <Button {...args} />;
export const Default = Template.bind({});
Default.args = {
label: 'My Button',
};
Once the files have been created, the Button component should be visible after restarting the storybook server.
Packaging our component
Now, it’s time to package our components and publish this package so that we can use them in another project.
First, let’s add components/index.js
this will be the entry point to our library and where we export our components:
// components/index.js
import Button from './Button';
export {
Button
};
Then we need to few more additional dev dependencies:
yarn add cross-env @babel/cli @babel/preset-env @babel/preset-react --dev
Also, add following to babel.config.js
to enable preset-env and preset-react to presets array
module.exports = function (api) {
api.cache(true);
const presets = [ "@babel/preset-env", "@babel/preset-react" ];
const plugins = [ "macros" ];
return {
presets,
plugins
};
}
To avoid any React conflict issues, we can move the following React dependencies to peer dependencies, as the app using this library will have React installed. (Peer dependencies: https://classic.yarnpkg.com/en/docs/dependency-types/ )
"peerDependencies": {
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.3"
}
Need to add following for publishing in package.json:
"main": "dist/index.js",
"files": [
"dist",
"README.md"
],
"repository": {
"type": "git",
"url": "URL_OF_YOUR_REPOSITORY"
},"private": false
We are almost there to publish our package. Let’s add compile script in package.json:
"clean": "rimraf dist",
"compile": "npm run clean && cross-env NODE_ENV=production babel src/components --out-dir dist --copy-files --ignore __tests__,spec.js,test.js,stories.js,__snapshots__"
Finally, build the package using and publish it to npm:
yarn compile
npm publish
Conclusion
Congratulations, now you have successfully publish a React component library with Storybook. This is the place where we can think about building the library more comprehensively. To use this package in another project, simply run following:
yarn add nibras-rakib-react-components
import {Button} from 'nibras-rakib-react-components';
For any question, please email me at : nibras.rakib@gmail.com