Creating reusable npm packages can make your development process more efficient and enjoyable. In this article, we'll guide you through creating a modern and robust project setup using React, TypeScript, CSS Modules, and other tools.
Before we start, you can find the source code here:
The key features include:
Let's dive into each tool more comprehensively.
CSS modules serve as a beacon of safety in the realm of styling chaos. They implement local scoping for your styles, warding off conflicts and overlap issues. Each CSS module will be "encapsulated" into the component, ensuring the styles you define won't leak out and affect other elements unintentionally.
Consider this simple component where we use CSS Module:
// TestComponent.tsx
import React from 'react';
import s from './TestComponent.module.css';
type TestComponentProps = {
text?: string;
};
export const TestComponent: React.FC<TestComponentProps> = ({ text }) => {
return <div className={s.root}>{text ?? 'Hello!'}</div>;
};
And its associated CSS Module:
/* TestComponent.module.css */
.root {
background-color: pink;
padding: 20px;
border-radius: 8px;
}
In this case, the .root
class from TestComponent.module.css
won't affect any other .root
class in a different module.
ESLint is like a lighthouse guiding you through a tumultuous sea of code. It helps maintain code quality, catching errors and enforcing best coding practices before they become problems.
In your package.json
, you have:
"scripts": {
"lint": "eslint './src/**/*.{ts,tsx}'"
}
Run the linter with npm run lint
. ESLint will scan through your TypeScript files and warn you about any potential issues. This is particularly handy for large codebases where it's easy for small errors or inconsistencies to creep in.
Rollup is your code's personal fitness trainer. It takes your JavaScript, TypeScript, and CSS and bundles them into one lean, efficient package ready for distribution.
It's lightweight and fast, but the real benefit comes from its "tree-shaking" capability. Rollup can eliminate unused code from the final bundle, making your package as lean as possible. Here's an example of how your Rollup configuration might look:
// rollup.config.js
const postcss = require('rollup-plugin-postcss');
const typescript = require('@rollup/plugin-typescript');
const peerDepsExternal = require('rollup-plugin-peer-deps-external');
const resolve = require('@rollup/plugin-node-resolve').default;
const commonjs = require('@rollup/plugin-commonjs');
module.exports = {
input: 'src/index.tsx',
output: {
dir: 'dist',
format: 'cjs',
sourcemap: true,
},
plugins: [
peerDepsExternal(),
resolve(),
typescript(),
commonjs(),
postcss({
modules: true,
}),
],
};
PostCSS is like a time-traveler, allowing you to write CSS using future syntax and features. It then travels back in time (so to speak), transforming these modern styles into code that even older browsers can understand.
You can see PostCSS in action in the Rollup configuration above. Using the rollup-plugin-postcss
, your modern CSS is transformed and included in your final bundle. The beauty of this is that you can write CSS using the latest features without worrying about browser compatibility.
Size Limit is the ever-vigilant watchman, making sure your library doesn't get too bloated. It calculates the real cost of your library by adding both the JavaScript and CSS that will be downloaded by users. It's a valuable tool to help you keep your bundle size in check.
In your package.json
:
"scripts": {
"size": "size-limit",
},
"size-limit": [
{
"path": "dist/*.js",
"limit": "10 KB"
}
]
You can then run npm run size
to check the size of your bundle. If it exceeds the limit you've set (in this case, 10 KB), the script will throw an error. It's a great way to ensure you're not unknowingly adding to your users' download times.
To start using this template, clone the repository:
git clone https://github.com/helgastogova/npm-react-typescript-template.git
Navigate into the directory:
cd npm-react-typescript-template
Install the dependencies:
npm install
You're all set to start developing your package! The entry point is src/index.tsx
After creating your own component and when you're ready to build your package for distribution, run:
npm run build
Your built package will be in the dist
directory, ready for publishing to npm.
Ensure that you've set the name
field in your package.json
to your desired package name. Also, remember to update the version number before each new publish. Once that's done, log in to npm using:
npm login
Enter your username, password, and email. Once logged in, you can publish your package with:
npm publish
Now you have published your component in the npmjs library, and people can start using it. You are awesome!
Happy coding!