Creating and Publishing a React Component Library as a NPM Package via React, Storybook and Rollup

Initiating Base Setup - any one from the two below

I. With NPM INIT

  1. Star with an empty folder and creates a package.json

    npm init
  2. Create directories:

    my-react-lib
      └── src
           ├── components
           └── index.js
  3. add dependencies only in development mode

    npm install --save-dev react react-dom
  4. Add a peerDependencies object in package.json and add the dev dependencies:

    "peerDependencies": {
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
    }

II. With create-react-app - Personal Suggestion, as i struggled with above method

  1. Star with an empty folder and initialise create-react-app

    npx create-react-app my-react-lib
  2. Add a peerDependencies object in package.json and add the dev dependencies:

    "peerDependencies": {
    	"react": "^17.0.2",
    	"react-dom": "^17.0.2"
    }

Installing StoryBook for Designing Components - (optional)

  1. Install StoryBook

    npx sb init

Note: Preparing to install dependencies. ✓ in terminal after installation indicates:
Dev-dependencies are already detected.

  1. Create new directory in components:

    my-react-lib
      └── src
           ├── components
           │     └──Reqirements
           └── index.js
  2. Create:

    my-react-lib
            ├── src
            ├── components
            │     └──Reqirements
            │		      ├──Requirements.jsx
            │		      └── index.js
            └── index.js
  3. Remember :

    the file src/index.js in src must have all components that
    need to be consumed as a package in the user's app
  4. After Creating a demo component(Requirements.jsx in our case);
    run storybook, just to check things are working, before which,
    make a story in stories directory:

    make a storybook stork, just to see whether the component is working or not

Installing Dependencies

  1. Installing rollup and other packages in devDependencies:

    $ npm install rollup rollup-plugin-babel @rollup/plugin-node-resolve rollup-plugin-peer-deps-external @babel/preset-react rollup-plugin-postcss rollup-plugin-terser --save-dev
  2. Function of each dependency:

    1. @rollup/plugin-node-resolve

      resolve third party dependencies, and add it to source code
    2. rollup

      to bundle the application
    3. rollup-plugin-babel

      allows to integrate with existing babel config
    4. rollup-plugin-peer-deps-external

      excludes any peerDependencies from our bundle, meaning exclude 'react' and 'react-dom' from our bundled source code.
    5. @babel/preset-react

      to handel JSX and other react goodies
    6. rollup-plugin-postcss

      to bundle all the css files
    7. rollup-plugin-terser

      to minify jsvascript

Configuring Rollup

  1. Making a Rollup Script to bundle the application,
    by creating a rollup.config.js file in root directory

    my-react-lib
      ├── src
      ├── package-lock.js
      ├── package.js
      └── rollup.config.js
  2. Configure the rollup.config.js file

    import babel from 'rollup-plugin-babel';
    import resolve from '@rollup/plugin-node-resolve';
    import external from 'rollup-plugin-peer-deps-external';
    import { terser } from 'rollup-plugin-terser';
    import postcss from 'rollup-plugin-postcss';
    
    // config for rollup
    export default [
    {
      // application entry point
      input: './src/index.js',
      // exporting our package
      output: [
        {
          file: 'dist/index.js',
          format: 'cjs',
        },
        {
          file: 'dist/index.es.js',
          format: 'es',
          exports: 'named',
        }
      ],
      plugins: [
        postcss({
          plugins: [],
          minimize: true,
        }),
        babel({
          exclude: 'node_modules/**',
          presets: ['@babel/preset-react']
        }),
        external(),
        resolve(),
        terser(),
      ]
    }
    ];

Changing package.json

  1. In package.json file, add the below Rollup script to bundle the app

    "build-lib": "rollup -c"
  2. also add these two lines in package.json, before publishing it to

    {
    	"main": "dist/index.js",
    	"module": "dist/index.es.js",
    }
  3. Final version of package.json:

    {
    	"name": "mm-demo-pkg",
    	"version": "0.1.0",
    	"description": "A React component library to Design React apps painlessly",
    	"author": "Apurv Chimralwar",
    	"main": "dist/index.js",
    	"module": "dist/index.es.js",
    	"license": "MIT",
    	"dependencies": {},
    	"peerDependencies": {
    		"react": "^17.0.2",
    		"react-dom": "^17.0.2",
    		"react-icons": "^4.2.0"
    	},
    	"scripts": {
    		"start": "react-scripts start",
    		"build": "react-scripts build",
    		"test": "react-scripts test",
    		"eject": "react-scripts eject",
    		"build-lib": "rollup -c"
    	},
    	"eslintConfig": {
    		"extends": "react-app"
    	},
    	"browserslist": {
    		"production": [
    			">0.2%",
    			"not dead",
    			"not op_mini all"
    		],
    		"development": [
    			"last 1 chrome version",
    			"last 1 firefox version",
    			"last 1 safari version"
    		]
    	},
    	"devDependencies": {
    		"@babel/core": "^7.14.0",
    		"@babel/preset-react": "^7.13.13",
    		"@rollup/plugin-node-resolve": "^11.2.1",
    		"react": "^17.0.2",
    		"react-dom": "^17.0.2",
    		"react-icons": "^4.2.0",
    		"rollup": "^2.46.0",
    		"rollup-plugin-babel": "^4.4.0",
    		"rollup-plugin-peer-deps-external": "^2.2.4",
    		"rollup-plugin-postcss": "^4.0.0",
    		"rollup-plugin-terser": "^7.0.2"
    	}
    }
    

Note before publishing it to npm

Before publishing it to npm via github repo make sure you are just pushing *dist, package.json and the readme.md*

Publishing to NPM

  1. Create an Npm Account

  2. Run the following command in terminal, and fill the npm account details

    $ npm login
  3. At last run npm publish, to publish to npm

    $ npm publish

Let’s build something

Tell me what you’re working on, or grab a slot on my calendar for a quick call.

Prefer email? [email protected]