This guide will walk you through the easiest process of building and releasing your NPM package, from start to finish, using a microbundle.

Let’s talk a bit about it microbundle. I find it particularly effective for simple libraries because you don’t have to worry about configuration, allowing you to focus on developing your package.

Here is a short list of its features:

Basically, microbundle is built on top of rollup.js. If you have more complex libraries to build than I will mention in this article, you might consider using a pure rollup.js configuration.

Initializing Your Package

As an example, let’s create a simple library for summing two numbers, which will export only one functionsum.

  1. Create a folder for the project, and run npm init with default values to generate package.json

  2. Create index.ts in src folder

    // src/index.ts
    export function sum(a: number, b: number) {
      return a + b;
    }
    
  3. Install microbundle

    npm i -D microbundle

  4. Updatepackage.json with the following values:

    // package.json
    ...
      "type": "module",
      "source": "src/index.ts", // your source code
      "exports": {
    		"types": "./dist/index.d.ts", // TypeScript declaration file
        "require": "./dist/index.cjs", // CommonJS entry point
        "default": "./dist/index.esm.js" // ES Module entry point
      },
      "main": "./dist/index.cjs", // where to generate the CommonJS bundle
      "module": "./dist/index.esm.js", // where to generate the ESM bundle
      "unpkg": "./dist/index.umd.js", // where to generate the UMD bundle
    	"types": "./dist/index.d.ts", // TypeScript declaration file for the package
    	"scripts": {
        "build": "microbundle", // compiles "source" to "main", "module", "unpkg"
        "dev": "microbundle watch" // re-build when source files change
      }
    ...
    
  5. Run the build script

    npm run build

    The output should contain exactly the files that we declared in package.json

And voilà, we made our first package. Let’s take a look at more complex scenarios.

Adding React Into Your Library

If you want to bring React to your library, you can still use itmicrobundle, but now, your build command should look like this:

microbundle --jsx React.createElement --jsxFragment React.Fragment --jsxImportSource react --globals react/jsx-runtime=jsx

Add the command to package.json into build script for future convenience:

// package.json
...
"scripts": {
  "build": "microbundle --jsx React.createElement --jsxFragment React.Fragment --jsxImportSource react --globals react/jsx-runtime=jsx"
}
...

Using Storybook for UI Components

While building a UI library, you might need a sandbox where you can develop, visualize components, and provide demo components for your documentation.

Here comes the storybook. It’s a sandbox with its own convenient interface and bundler, where you can easily describe various states of your components. Each capture of your component state is called a "story."

This picture, taken from their documentation, shows what it looks like:

Installing Storybook is quite simple; just run the command inside your library:

npx storybook@latest init

This command will install all required dependencies for Storybook, add scripts to run, and build Storybook into package.json , create a folder .storybook with default configuration, and add some examples of stories to the foldersrc/stories.

Integrating Styling Into Your Library

You can add styling in one of two ways: CSS file or CSS-in-JS. The CSS file allows easy customization but requires separate inclusion, whereas the CSS-in-JS simplifies styling but increases bundle size.

Choose the option that suits you best. I prefer to use the CSS file because it allows users to customize any element with CSS selectors, doesn’t affect the bundle size, and works faster.

Developing a Detailed README.md File

A README.md file provides information about your library, how to install it, its basic usage, and the features it has. This is often the first file that developers read when they encounter your repository or NPM package, so it should be concise and informative.

I like to create a structure in the following order:

  1. Title
  2. Super short package description
  3. Fancy statistic badges (shields.io)
  4. If your library is a UI component, include a screenshot or provide a demo link on CodeSandbox
  5. Features list
  6. Installation guide
  7. Code fragments with usage
  8. Options and props that your library accepts for configuration

You can refer to examples ofREADME.md files from my packages, such as dot-path-value and react-nested-dropdown, for inspiration.

Navigating Dependency Management

This is an important part because if you do it wrong, users may face version conflicts or other problems, and they will have to remove your library. So, let's take a look at the main differences between dependency types.

Just a small example of how it looks:

// package.json
...
"dependencies": { // libraries which will be installed along with your library
    "clsx": "^1.2.1" // just library for className combining
  },
"peerDependencies": { // user should have these packages installed
  "react": "^16.8.0 || ^17.0.0 || ^18.0.0" // user should have react 16.8+ version
},
"devDependencies": { // won't be in user's bundle, these libraries just for your developing needs
    "@types/react": "^18.2.33",
		"react": "^18.2.0", // in case if we are using storybook, we need actual react library to render our components there
    "microbundle": "^0.15.1",
},
...

Using GitHub for Your Package

If you are publishing an NPM package, it means it will be publicly accessible (if you have a free account). To gather feedback from users, you can create a GitHub repository for your original code. People can create issues and communicate with you about your package there. You can also describe your releases and get some stars!

You can certainly skip this step, but it is an integral part of the developer culture and can be a valuable contribution to open-source.

Publishing and Maintaining the Package

Before you can publish your package, it's essential to ensure that your package.json file is properly configured. Here are some important steps to follow:

  1. Name and try to describe the core functionality of your library. For example:

    "name": "react-color-picker"
    

  2. Add GitHub repository information (if it exists):

    ...
    "homepage": "https://github.com/{your_repository}",
    "repository": {
        "type": "git",
        "url": "https://github.com/{your_repository}"
      },
    "bugs": {
        "url": "https://github.com/{your_repository}/issues"
      },
    ...
    

  3. Configure the files :

    ...
    "files": [
        "dist",
    ],
    ...
    

    You should specify the files that will be included in node_modules, when your library is installed. Usually, including the dist folder is sufficient.

  4. Add keywords :

    Keywords are an array of strings that describe your package and are used by NPM for searches and recommendations. Choose words relevant to your package that you anticipate people will use when searching. Let’s create keywords for our sum library:

    ...
    "keywords": ["typescript", "math", "sum", "numbers", "arithmetic", "calculator", "calculation"]
    ...
    

    It’s important to specify your technologies because users often search for terms like “typescript library for math” or “react calendar picker.”

  5. Create an NPM account if you haven’t already, and run npm login in your terminal; follow the prompts to authenticate your account. By default, the version of your package will be 1.0.0; you can check it in the package.json file. I recommend changing it to 0.0.1.

  6. Run npm publish, and you're done! To update the version in the future, use the command npm version patch to increment the version, and then publish the updated package with npm publish.

Conclusion

As you can see, creating your own library is very easy! Essentially, this is all you need for creating and maintaining the package. If you struggle with limiting your library with microbundle, I recommend using rollup.js with a more specific configuration.

Creating NPM packages and contributing to open-source is a rewarding and valuable experience for developers of all skill levels. It allows you to share your code with the community, gain a lot of experience, and build a portfolio of your work.