[Part 1] - Build & Publish React component as NPM package using Typescript compiler
![[Part 1] - Build & Publish React component as NPM package using Typescript compiler](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680502323468%2Fb83337d6-0fd5-4d4e-90a1-5176f094293d.png&w=3840&q=75)
Frontend Developer at Thoughtworks
Search for a command to run...
![[Part 1] - Build & Publish React component as NPM package using Typescript compiler](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680502323468%2Fb83337d6-0fd5-4d4e-90a1-5176f094293d.png&w=3840&q=75)
Frontend Developer at Thoughtworks
No comments yet. Be the first to comment.
Recently, I had the chance to work on SEO (Search Engine Optimization) for one of the projects. I learned a few things along the way. You can follow these steps: Google doesn’t accept any payment to make any website rank better, it all depends on the...

Micro interactions are common on most websites and mobile apps these days to enhance the user experience. I tried creating a simple micro interaction for my portfolio web app. While this could be done with CSS alone, but it is really complex. I found...

Story Behind the Blog Until recently, we managed all our form data using MobX. However, after introducing React Hook Form, form validation became much simpler. We realized that there was no need to save the form data in multiple places since React Ho...

Let's go through the steps to migrate your frontend repo to Vite

build times are high? Give Vite a try

I was too lazy to include webpack to bundle the react component as it needs a lot of boilerplate configuration code. so easiest way was to build the react typescript project using the typescript compiler with a little help from tsc-hooks.
you can follow the steps to know more about building and publishing a react project without the use of webpack.
mkdir toggle-button
yarn init
or
npm init
yarn add -D react react-dom @types/react @types/react-dom typescript tsc-hooks
or
npm install --save-dev react react-dom @types/react @types/react-dom typescript tsc-hooks
Update react as peer dependency so that the user of this package will be prompted to install react while adding this package.
now the package.json should look like -
package.json
{
"name": "react-toggle-button",
"version": "0.0.1",
"description": "React toggle button",
"main": "dist/", // update this
"scripts": {
"test": "yarn test",
"build": "tsc" // runs tsc compiler to build the project in dist directory (configured in tsconfig.json)
},
"repository": {
"type": "git",
"url": "git+https://github.com/YOUR-REPO/react-toggle-button.git"
},
"keywords": [
"react",
"react-toggle-button"
],
"author": "AUTHOR NAME",
"license": "ISC",
"bugs": {
"url": "https://github.com/YOUR-REPO/react-toggle-button/issues"
},
"homepage": "https://github.com/YOUR-REPO/react-toggle-button#readme",
"devDependencies": {
"@types/react": "^18.0.18",
"react": "^18.2.0",
"tsc-hooks": "^1.1.1", // needed to copy css files in the final build
"typescript": "^4.8.3"
},
"peerDependencies": {
"react": "^18.2.0" // add react as a peer dependency
},
"files": [
"/dist" // tells the bundler to only add dist folder while publishing the package. package.json will be automatically added.
]
}
now let's add tsconfig.json for the typescript compiler to know where and how to build the typescript files.
tsconfig.json
{
"compilerOptions": {
"target": "ES2015",
"jsx": "react",
"module": "esnext",
"moduleResolution": "node",
"allowJs": true,
"declaration": true, // required to generate corresponding *.d.ts files
"outDir": "./dist",
"esModuleInterop": true,
"strict": true,
"noImplicitAny": true,
},
"exclude": [
"node_modules",
],
"hooks": [
"copy-files" // copies all files to the dist folder
],
"include": [
"src/",
"src/**/*.module.css" // include css files while building the project using tsc
]
}
if you want to avoid copying all files to the final build then another workaround is to use a package copyfiles and add a script in package.json to manually copy selective files. For eg. In this case we are copying all css files.
package.json
...
"copy-files": "copyfiles -u 1 src/**/*.css dist/",
...
Add .npmignore to exclude src files from the final npm package build.
.npmignore
/src
Now lets add the react component in the src directory
src/ToggleButton/ToggleButton.tsx
import React from "react";
import styles from "./ToggleButton.module.css";
interface ToggleButtonProps {
onClick: () => void;
value: boolean;
}
const ToggleButton = ({ onClick, value }: ToggleButtonProps) => {
function clickHandler() {
onClick();
}
return (
<div
id={value ? "on" : "off"}
className={styles.toggleButton}
onClick={clickHandler}
>
<div className={styles.bar}>
<div className={styles.circle}></div>
</div>
</div>
);
};
export default ToggleButton;
src/ToggleButton/ToggleButton.module.css
.toggleButton {
position: relative;
width: 36px;
height: 1rem;
display: flex;
align-items: center;
}
.circle {
width: 17px;
height: 17px;
border-radius: 50%;
position: absolute;
top: 50%;
transform: translateY(-50%);
transition: all 0.3s ease-in;
--on : #eb5757;
--off: #e0e0e0;
}
.bar {
height: 20px;
width: 100%;
border-radius: 50px;
padding: 2px;
}
#on .bar {
background-color: var(--on);
}
#off .bar {
background-color: var(--off);
}
#on .circle {
background-color: var(--on);
left: calc(100% - 19px);
}
#off .circle {
background-color: var(--off);
left: 2px;
}
Add declarations.d.ts file so that typescript compliler know about the *.module.css files.
src/declarations.d.ts
declare module '*.module.css' {
const classes: { [key: string]: string };
export default classes;
}
Directory structure should look like -

Don't forget to add a README.md file in the root directory with all the installation and usage of the package you are deploying. I am skipping this step in the example.
Lets run tsc compiler to generate the respective files in dist directory -
yarn build // spits the output files in the dist/ directory
now we are ready to publish the package. If you are deploying for the first time - create an npm account and login in the terminal.
npm login // skip this if you are already logged in
npm publish
Update the package version before every publish otherwise the publish will fail.