Techumber

Rollup React Library

Github avatar
Dimpu
July 24, 2020. 6 min read

Intro

Rollup is a module bundler to compile the Javascript code. In the previous post explained rollup basics.

In this post let’s see how we can build and publish react library using rollup and npm.

Requirements

We have the following requirements.

  1. React
  2. Typescript
  3. SASS
  4. Eslint
  5. Storybook support
  6. Yarn/Npm
  7. Semantic Versioning

The Component Library

Create a new folder rollup-react-libarary. Initilize npm with yarn init and git init

yarn init
yarn init v1.22.4
question name (rollup-react-library):
question version (1.0.0):
question description: rollup react library
question entry point (index.js): dist/index.umd.js
question repository url: http://github.com/dimpu/rollup-react-library.git
question author (dimpu):
question license (MIT):
question private: false
success Saved package.json
✨  Done in 72.06s.

Since we are creating react library we need to add react, react-dom as peer dependency.

yarn add react react-dom -P
yarn add @types/react typescript -D

Now you should see following in your package.json

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

Eslint

Add eslint

npx eslint --init

Answer few questions

npx: installed 107 in 4.737s
? How would you like to use ESLint? …
  To check syntax only
  To check syntax and find problems
❯ To check syntax, find problems, and enforce code style

✔ How would you like to use ESLint? · style
? What type of modules does your project use? …
❯ JavaScript modules (import/export)
  CommonJS (require/exports)
  None of these

✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
? Which framework does your project use? …
❯ React
  Vue.js
  None of these

✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
? Which framework does your project use? …
❯ React
  Vue.js
  None of these

✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · No / Yes
? Where does your code run? …  (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
✔ Node

✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · No / Yes
? Where does your code run? …  (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
✔ Node


✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser, node
? How would you like to define a style for your project? …
❯ Use a popular style guide
  Answer questions about your style
  Inspect your JavaScript file(s)

✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser, node
? How would you like to define a style for your project? …
❯ Use a popular style guide
  Answer questions about your style
  Inspect your JavaScript file(s)

This will add all required packages.

Then add lint command to scripts.

scripts: {
....
lint: eslint src/**/*.{tsx,ts}
lint-fix: eslint src/**/*.{tsx,ts} -- --fix
....
}

Storybook

To setup storybook run

npx -p @storybook/cli sb init

This will setup storybook and adds storybook packages and command to package.json scripts.

By default storybooks only support Javascript. We need to support Typescript and sass so let’s add it.

yarn add ts-loader @storybook/addon-info react-docgen-typescript-loader style-loader css-loader sass-loader -D

Then update .storybook/main.js

module.exports = {
  stories: ["../src/**/*.stories.tsx"],
  addons: ["@storybook/addon-actions", "@storybook/addon-links"],
  webpackFinal: async (config) => {
    config.module.rules.push(
      {
        test: /\.(ts|tsx)$/,
        use: [
          {
            loader: require.resolve("ts-loader"),
          },
          {
            loader: require.resolve("react-docgen-typescript-loader"),
          },
        ],
      },
      {
        test: /\.s[ac]ss$/i,
        use: ["style-loader", "css-loader", "sass-loader"],
      }
    );
    config.resolve.extensions.push(".ts", ".tsx");
    return config;
  },
};

Run yarn storybook to run the storybook.

Source Code

Let’s create src folder.

Let’s add Gavatar component to the source.

Gavatar.tsx

import React, { useEffect, useState } from 'react';
import md5 from 'md5';
import styles from './Gavatar.scss';

interface Props {
  email: string;
  size?: number;
}

export default ({ email, size = 300 }: Props) => {
  const [emailMd5, setEmailMd5] = useState('//www.gravatar.com/avatar/');

  useEffect(() => {
    setEmailMd5(`//www.gravatar.com/avatar/${md5(email)}?s=${size}`);
  }, [email]);

  return (
    <div className={styles.box}>
      <img alt="" src={emailMd5} />
    </div>
  );
};

Gavatar.scss

.box {
  border: 1px solid #ccc;
  width: 300px;
  height: 300px;
  img {
    padding: 5px;
    background: #fff;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
    width: 100%;
    height: 100%;
    border: 1px solid #ddd;
  }
}

Gavatar.stories.ts

import React from 'react';
import Gavatar from './Gavatar';

export default {
  title: 'Gavatar',
  component: Gavatar,
};

export const GavatarStory = () => <Gavatar email="<your email" />;

That’s now if you already running Storybook using yarn storbook you should see

image-20200802110949827

Rollup

Let add rollup to the repo.

yarn add rollup @rollup/plugin-typescript rollup-plugin-scss @rollup/plugin-commonjs -D

Add rollu.config.js

import typescript from '@rollup/plugin-typescript';
import scss from 'rollup-plugin-scss';
import commonjs from '@rollup/plugin-commonjs';
import pkg from './package.json';

export default {
  input: 'src/index.tsx',
  output: [
    {
      file: pkg.main,
      format: 'umd',
    },
    {
      file: pkg.module,
      format: 'esm',
    },
  ],
  plugins: [
    commonjs(),
    scss({
      output: true,
    }),
    typescript(),
  ],
};

Update package.json

{
  .....
  "main": "dist/rollup-react-library.umd.js",
  "module": "dist/rollup-react-library.esm.js",
  ....
  "scripts": {
		....
		"build": "rollup -c"
  }
}

That’s it now if you run yarn build you should see a dist folder generated with *.umd.js & *.ems.js.

Yarn Publish

To distrubute your package as node module. Just run yarn publish

Source: https://github.com/dimpu/rollup-react-library


...