70
Creating React TypeScript component library - basic rollup.js setup
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!
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!
This article is based on these sources:
As I am writing this article I'm using:
- node v14.17.0
- npm v6.14.10
Obviously, we need some new directory for our library:
mkdir my-ui-library
cd my-ui-library
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
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"
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.
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
How we are able to build our library? Just specify the build script:
"build": "rimraf dist && tsc --emitDeclarationOnly && rollup --config",
"tsc": "tsc"
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
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"
]
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"
]
}
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
};
Next, create some simple TypeScript file:
// @/src/index.ts
const Component = () => {};
export default Component;
Congrats, you've made it to this place!
Now, simply run this npm script:
npm run build
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
- 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
70