Creating React TypeScript component library - basic rollup.js setup

kraftdorian

Damian

Posted on July 20, 2021

Creating React TypeScript component library - basic rollup.js setup

Intro

I have worked on several custom front-end projects and often thought about using the same styles and/or components, so other developers could use consistent UI.

Too long I was afraid of creating a separate library, so usually, I was ending up including the components directly in the project files.

That's not the case here!

What is it about?

This is the first article I have created in a series "Creating React TypeScript component library with rollup.js from scratch".
Hopefully, the title explains the article's contents.

It's all about configuration and installing proper libraries. I won't give it too much attention, just quickly explain what is necessary and why.

If you want to see the whole code as it is at the end of this tutorial, just feel free to visit this repo at my GitHub account.
Also, give it a star if you want!

Important note

This article is based on these sources:

A few words about the versions

As I am writing this article I'm using:

  • node v14.17.0
  • npm v6.14.10

Let's start!

Armory

Obviously, we need some new directory for our library:

mkdir my-ui-library
cd my-ui-library
Enter fullscreen mode Exit fullscreen mode

Then, we initialize it (you will be prompted to type some stuff. If you don't want to be that specific, then you can use default values by constantly pressing ENTER):

npm init
Enter fullscreen mode Exit fullscreen mode

In the end, make sure you set this file as your main script in package.json (it doesn't exist now, but we will build it!):

"main": "dist/index.js"
Enter fullscreen mode Exit fullscreen mode

2021-11-24 UPDATE - TypeScript compiler only

If you want to use TypeScript compiler only, please have a look at this rollup.config.js instead, as well as the updated package.json.

Don't forget to create tsconfig.json as well.

Then, feel free to jump straight to the Finale section.

More details about the original issue are available here.

Arrival (of dev dependencies!) - compile with babel (legacy section)

We will compile our TypeScript components with Babel.
Types will be generated with TypeScript's compiler.

It's important to save these deps in dev dependencies - the project where we will put our library doesn't need to have them!

npm i --save-dev rollup rollup-plugin-peer-deps-external @rollup/plugin-node-resolve @rollup/plugin-babel @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript @babel/plugin-transform-runtime @babel/runtime @babel/plugin-proposal-class-properties typescript tslib rimraf
Enter fullscreen mode Exit fullscreen mode

The Grid (where we will work)

How we are able to build our library? Just specify the build script:

"build": "rimraf dist && tsc --emitDeclarationOnly && rollup --config",
"tsc": "tsc"
Enter fullscreen mode Exit fullscreen mode

If you're stuck here, feel free to check this package.json.

At this point, we need to somehow run tsc to initialize our TypeScript config. If for some reason tsc is not available for you, try adding it to package.json scripts.

npm run tsc -- --init
Enter fullscreen mode Exit fullscreen mode

We don't need all the config options that tsc has created.
You can go ahead and grab the ones I prepared in this tsconfig.json.
You can read more about tsconfig here.

The important thing above is, we want to include our TypeScript files, but exclude node_modules and our built files directory.

"include": [
  "src/**/*.ts",
  "src/**/*.tsx"
],
"exclude": [
  "node_modules",
  "dist"
]
Enter fullscreen mode Exit fullscreen mode

As for Babel, we need to configure it in the babel.config.json file:

{
  "presets": [
    "@babel/preset-env",
    "@babel/preset-typescript",
    "@babel/preset-react"
  ],
  "plugins": [
    "@babel/proposal-class-properties",
    "@babel/proposal-object-rest-spread"
  ]
}
Enter fullscreen mode Exit fullscreen mode

Arena (rollup.js vs TypeScript)

Simply place this configuration in your rollup.config.js at the project root:

import babel from "@rollup/plugin-babel";
import resolve from "@rollup/plugin-node-resolve";
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import pkg from "./package.json";

// Array of extensions to be handled by babel
const EXTENSIONS = [".ts", ".tsx"];

// Excluded dependencies - dev dependencies
const EXTERNAL = Object.keys(pkg.devDependencies);

export default {
  input: ["src/index.ts"],  // What files we build?
  output: {
    dir: "dist",  // Directory where rollup.js will put the built files
    sourcemap: true,  // We want a source map to trace the original code
    format: "esm",  // Built files will follow ES Module format
    preserveModules: true  // This one is important for treeshaking features of our library
  },
  plugins: [
    peerDepsExternal(),  // https://rollupjs.org/guide/en/#peer-dependencies
    resolve(),  // Resolves node modules
    babel({
      extensions: EXTENSIONS,  // Compile our TypeScript files
      babelHelpers: "runtime",  // EDIT(2021-11-18): "inline" is not recommended. Please see the details in https://github.com/kraftdorian/react-ts-rollup-starter-lib/issues/1
      include: EXTENSIONS.map(ext => `src/**/*${ext}`),
      plugins: ["@babel/plugin-transform-runtime"]
    })
  ],
  external: EXTERNAL  // https://rollupjs.org/guide/en/#peer-dependencies
};
Enter fullscreen mode Exit fullscreen mode

Next, create some simple TypeScript file:

// @/src/index.ts

const Component = () => {};

export default Component;
Enter fullscreen mode Exit fullscreen mode

Finale

Congrats, you've made it to this place!
Now, simply run this npm script:

npm run build
Enter fullscreen mode Exit fullscreen mode

If everything is good, you will see:
Console output after build

These files will appear in the dist directory:
dist directory contents

Summary

We have just created a basic project that allows us to compile TypeScript to JavaScript with Babel, and the types are generated by the TypeScript compiler.

For further reference, all files I have presented here you can find in my repository:
https://github.com/kraftdorian/react-ts-rollup-starter-lib/tree/1.1.0

2021-11-18 UPDATE

Changed

  1. Use "runtime" instead of "inline" in rollup.config.js as the "inline" helpers are not recommended. Please visit https://github.com/kraftdorian/react-ts-rollup-starter-lib/issues/1 for more details.

Article cover photo: https://unsplash.com/photos/-LFxVNhopfs

💖 💪 🙅 🚩
kraftdorian
Damian

Posted on July 20, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related