Chronological guide: Building & Publishing a React Library

Just a guy who loves to write code and watch anime.
Search for a command to run...

Just a guy who loves to write code and watch anime.
No comments yet. Be the first to comment.
Qualities that make outstanding builders.

Bipedal vs quadrupedal: how many legs This is about the number of legs the creature walks on. Bipedal. Two legs. Humans, ostriches, T-rex, kangaroos, most fantasy humanoids. Quadrupedal. Four legs. Do

Intro You hear "lerp" and "smoothstep" everywhere in game dev. They sound like math jargon. They're not. Both are small tools that do the same job: smoothly move from one value to another. The problem

What is Kinematics Kinematics is the math field. It's the study of how things move without worrying about forces (which would be dynamics). FK and IK are the two branches: forward kinematics and inver

Intro Textures are usually the biggest cost in a 3D scene. Memory, bandwidth, and load time all get eaten by them. Resizing them is the obvious lever. There's more. This post is about the less obvious

# Create project directory
mkdir my-react-library
cd my-react-library
# Initialize with pnpm
pnpm init
# Install React as peer dependencies (users will provide these)
pnpm add react react-dom --save-peer
# Install TypeScript and build tools
pnpm add -D typescript @types/react @types/react-dom tsup
# Install React types for development
pnpm add -D react react-dom
my-react-library/
├── src/
│ ├── index.ts
│ └── components/
│ └── HelloWorld.tsx
├── package.json
├── tsconfig.json
├── tsup.config.ts
└── README.md
Create src/components/HelloWorld.tsx:
import React from "react";
interface HelloWorldProps {
name?: string;
className?: string;
}
export const HelloWorld: React.FC<HelloWorldProps> = ({
name = "World",
className = "",
}) => {
return (
<div className={`hello-world ${className}`}>
<h1>Hello, {name}!</h1>
<p>This is my first React library component.</p>
</div>
);
};
Create src/index.ts:
export { HelloWorld } from "./components/HelloWorld";
export type { HelloWorldProps } from "./components/HelloWorld";
Create tsconfig.json:
{
"compilerOptions": {
"target": "ES2020",
"lib": ["DOM", "DOM.Iterable", "ES6"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"declaration": true,
"outDir": "./dist"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
Create tsup.config.ts:
import { defineConfig } from "tsup";
export default defineConfig({
entry: ["src/index.ts"],
format: ["cjs", "esm"],
dts: true,
splitting: false,
sourcemap: true,
clean: true,
external: ["react", "react-dom"],
});
{
"name": "@yourscope/my-react-library",
"version": "0.1.0",
"description": "My first React library",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"default": "./dist/index.js"
}
},
"files": ["dist"],
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"prepublishOnly": "pnpm build"
},
"keywords": ["react", "component", "library", "typescript"],
"author": "Your Name",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/yourusername/my-react-library"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
},
"devDependencies": {
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"tsup": "^8.0.0",
"typescript": "^5.0.0"
},
"publishConfig": {
"access": "public"
}
}
# Build the library
pnpm build
# Check the output in dist/
ls -la dist/
You should see:
index.cjs (CommonJS)
index.js (ESM)
index.d.ts (TypeScript definitions)
Source maps
# Test if the package can be imported
node -e "console.log(require('./dist/index.cjs'))"
A simple React component library.
npm install @yourscope/my-react-library
# or
pnpm add @yourscope/my-react-library
import { HelloWorld } from "@yourscope/my-react-library";
function App() {
return (
);
}
A simple greeting component.
name?: string -> The name to greet (default: "World")className?: string -> Additional CSS classesMIT
src/
tsconfig.json
tsup.config.ts
*.log
node_modules/
.DS_Store
# Check what will be published
pnpm pack --dry-run
# Or create a tarball to inspect
pnpm pack
tar -tzf *.tgz
# Login to npm
pnpm login
# Verify you're logged in
pnpm whoami
# Make sure everything is built
pnpm build
# Publish to npm
pnpm publish
After making changes to your library:
# Update version (patch: 0.1.0 -> 0.1.1)
pnpm version patch
# Or minor version (0.1.0 -> 0.2.0)
pnpm version minor
# Or major version (0.1.0 -> 1.0.0)
pnpm version major
# Build and publish
pnpm build
pnpm publish
Add to package.json scripts:
{
"scripts": {
"build": "tsup",
"dev": "tsup --watch",
"prepublishOnly": "pnpm build",
"version": "pnpm build && git add dist/",
"postversion": "git push && git push --tags"
}
}
To test your library in another project before publishing:
# In your library directory
pnpm link
# In your test project
pnpm link @yourscope/my-react-library
# Setup
pnpm init
pnpm add react react-dom --save-peer
pnpm add -D typescript @types/react @types/react-dom tsup
# Development
pnpm dev # Watch mode
pnpm build # Build library
# Publishing
pnpm version patch # Update version
pnpm publish # Publish to npm
# Testing
pnpm link # Link for local testing
pnpm pack --dry-run # Check package contents