Have you ever wondered how libraries like Material UI and Tailwind CSS are built and published? Trust me, it's much easier than you think. In this guide, we'll walk through the process of taking our toast component and publishing it to NPM.
Publishing your own libraries can enhance your resume, potentially landing you a job or freelance clients. It’s a valuable skill that looks impressive in your portfolio.
If you're someone who likes to watch videos more, Here's the video version of this blog -
What We'll Cover
Introduction to the React TypeScript NPM library we'll create
Explanation of NPM (Node Package Manager) and what an NPM library is
Setting up the project
Compiling TypeScript files
Bundling using Rollup
Publishing to NPM
Setting up the Project
We have a pre built React with TypeScript Toast component. You can watch the full video of building this component here.
Create a new folder for your project.
Copy the
src
folder from your toast component and delete all global files and create anindex.ts
file exporting our component.import useNotification from "./hooks/useNotification"; export default useNotification;
It should look something like this -
Install necessary dependencies like React, TypeScript, and tslib.npm i react typescript @types/react tslib --save-dev
npm i react typescript @types/react tslib --save-dev
Compiling TypeScript Files
Create a tsconfig.json
file by running:
npx tsc -init
Here is the essential configuration we need in tsconfig.json
:
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"]
}
Explanation of Key Options
"target": "es5"
: Ensures compatibility with older browsers."lib": ["dom", "dom.iterable", "esnext"]
: Includes necessary libraries."allowJs": true
: Allows processing of JavaScript files."skipLibCheck": true
: Skips type checks for libraries."esModuleInterop": true
: Enables ES module interoperability."allowSyntheticDefaultImports": true
: Allows default imports."strict": true
: Enables strict type-checking."forceConsistentCasingInFileNames": true
: Enforces consistent file name casing."noFallthroughCasesInSwitch": true
: Prevents fall-through cases in switch statements."module": "esnext"
: Uses ESNext module system."moduleResolution": "node"
: Uses Node.js module resolution."resolveJsonModule": true
: Resolves JSON modules."isolatedModules": true
: Isolates each module."noEmit": true
: Prevents emitting JavaScript files."jsx": "react-jsx"
: Uses React JSX factory.
Bundling Using Rollup
Now that we have compiled our code, we need to bundle it for different environments.
( Bdw, I have recently released a Complete Frontend Interview Prep Course, you might wanna check it out here - https://roadsidecoder.com/course-details )
Install Rollup:
npm i rollup
Install additional plugins:
npm i @rollup/plugin-node-resolve @rollup/plugin-commonjs @rollup/plugin-typescript rollup-plugin-peer-deps-external @rollup/plugin-terser rollup-plugin-dts --save-dev
@rollup/plugin-node-resolve
: Resolves dependencies in your code.@rollup/plugin-commonjs
: Allows use of CommonJS modules.@rollup/plugin-typescript
: Enables TypeScript support.rollup-plugin-peer-deps-external
: Manages peer dependencies.@rollup/plugin-terser
: Minifies JavaScript code.rollup-plugin-dts
: Generates type declarations.
Create
rollup.config.js
:- Add following keys to
package.json
- Add following keys to
{
...
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
...
}
- Writing the config (
rollup.config.js
) -
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import typescript from "@rollup/plugin-typescript";
import dts from "rollup-plugin-dts";
import terser from "@rollup/plugin-terser";
import peerDepsExternal from "rollup-plugin-peer-deps-external";
const packageJson = require("./package.json");
export default [
{
input: "src/index.ts",
output: [
{
file: packageJson.main,
format: "cjs",
sourcemap: true,
},
{
file: packageJson.module,
format: "esm",
sourcemap: true,
},
],
plugins: [
peerDepsExternal(),
resolve(),
commonjs(),
typescript({ tsconfig: "./tsconfig.json" }),
terser(),
],
external: ["react", "react-dom"],
},
{
input: "src/index.ts",
output: [{ file: packageJson.types }],
plugins: [dts.default()],
},
];
format: "cjs"
: Output as CommonJS module.format: "esm"
: Output as ES module.external
: Excludes specified dependencies from the bundle.
Build Script:
{ ... "scripts": { "rollup": "rollup -c --bundleConfigAsCjs", ... } }
Explanation of the Build Script
"rollup": This is the name of the script. You can run it using
npm run rollup
."rollup -c --bundleConfigAsCjs": This command runs Rollup with the specified options:
-c
: Tells Rollup to use a configuration file (rollup.config.js
by default).--bundleConfigAsCjs
: Ensures the output is bundled as a CommonJS module.
Handling CSS:
- Install the postcss plugin:
npm i rollup-plugin-postcss
- Update
rollup.config.js
:
import postcss from "rollup-plugin-postcss";
...
plugins: [
...
postcss(),
],
external: [/\.css$/]
...
Here's our final rollup configuration file -
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import typescript from "@rollup/plugin-typescript";
import dts from "rollup-plugin-dts";
import terser from "@rollup/plugin-terser";
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import postcss from "rollup-plugin-postcss";
const packageJson = require("./package.json");
export default [
{
input: "src/index.ts",
output: [
{
file: packageJson.main,
format: "cjs",
sourcemap: true,
},
{
file: packageJson.module,
format: "esm",
sourcemap: true,
},
],
plugins: [
peerDepsExternal(),
resolve(),
commonjs(),
typescript({ tsconfig: "./tsconfig.json" }),
terser(),
postcss(),
],
external: ["react", "react-dom"],
},
{
input: "src/index.ts",
output: [{ file: packageJson.types }],
plugins: [dts.default()],
external: [/\.css$/],
},
];
Publish to NPM
Finally, you can publish your package to NPM by following these steps:
Log in to NPM:
npm login
Publish the package:
npm publish
And that's it! You've successfully created and published a React TypeScript component to NPM.
Here's the library I published - https://www.npmjs.com/package/react-toast-popup