DEV Community

Simon Boisset
Simon Boisset

Posted on • Edited on • Originally published at simonboisset.com

Create and publish npm module library with esbuild typescript and react

Introduction

As an open source enthusiast, I like to share my code and give everyone the opportunity to use it. For that npm is my first choice. But there are some conditions to have a good library release on npm.

The first recommendation to follow is to support common js as Matteo Collina said :

Here is my recommendation to all my fellow npm module authors: don’t drop support for CJS and go esm-only. The community is not ready to migrate just yet. Matteo Collina (@matteocollina) August 19, 2022

For long time you needed to use js bundler like rollup, webpack and babel.

But that time is over because of a new generation of bundler. esbuild is one of them.

Today we will see how to create and publish a react library on npm with esbuild.

You can go to this repository for an example of this post.

Initialization

Create your folder project and initialize it.

yarn init
Enter fullscreen mode Exit fullscreen mode

Your package.json file should be defined :

{
  "name": "my-react-library",
  "version": "1.0.0"
}
Enter fullscreen mode Exit fullscreen mode

Now we will install our dependencies.

Install dev dependencies

yarn add -D react react-dom typescript @types/react @types/react-dom
Enter fullscreen mode Exit fullscreen mode

Don't forget to add react as a peer dependency if you are writing a react library with hooks or components.

"peerDependencies": {
   "react": ">=16"
 },
Enter fullscreen mode Exit fullscreen mode

Typescript config

Add tsconfig.json file.

{
  "include": ["src"],
  "compilerOptions": {
    "module": "esnext",
    "target": "esnext",
    "lib": ["dom", "dom.iterable", "esnext"],
    "declaration": true,
    "strict": true,
    "moduleResolution": "node",
    "jsx": "react",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "emitDeclarationOnly": true,
    "outDir": "dist",
    "rootDir": "src"
  }
}
Enter fullscreen mode Exit fullscreen mode

we don't need to build file with typescript because we will use esbuild for that. That's why emitDeclarationOnly is set to true

Write your module

Now you can write what you want. For example we will just write a function component to export.

Create src folder then index.tsx inside it.

export const MyComponent = () => {
  return <div>Hello word</div>
}
Enter fullscreen mode Exit fullscreen mode

Build your library

Now we need to build our package to CJS before publish it to npm.

Configure esbuild

Add esbuild :

yarn add -D esbuild esbuild-node-externals
Enter fullscreen mode Exit fullscreen mode

Create an esbuild script for the bundle. Add a file esbuild.js :

const esbuild = require('esbuild');
const { nodeExternalsPlugin } = require('esbuild-node-externals');
esbuild
  .build({
    entryPoints: ['./src/index.ts'],
    outfile: 'dist/index.js',
    bundle: true,
    minify: true,
    treeShaking: true,
    platform: 'node',
    format: 'cjs',
    target: 'node14',
    plugins: [nodeExternalsPlugin()],
  })
  .catch(() => process.exit(1));
Enter fullscreen mode Exit fullscreen mode

Add a build commande

And finally add a script in your package.json :

 "scripts": {
    "build": "rm -rf dist && node esbuild.js && tsc"
  },
Enter fullscreen mode Exit fullscreen mode

Now you can run :

yarn build
Enter fullscreen mode Exit fullscreen mode

Npm publish

Before publishing you need to be authenticated

Add these lines to your package.json :

 "main": "dist/index.js",
  "files": [
    "dist"
  ],
Enter fullscreen mode Exit fullscreen mode

Then publish it :

npm publish
Enter fullscreen mode Exit fullscreen mode

Congratulations, you have published your own library.

Publish package with Github action

Finally we just want to publish package when we trigger a github action. For that we have to add a file to .github/workflows/publish.yml:

name: Publish
on:
  workflow_dispatch:
    inputs:
      release:
        description: 'major | minor | patch'
        required: true
        default: 'patch'
        type: choice
        options:
          - major
          - minor
          - patch
jobs:
  publish-new-version:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout main
        uses: actions/checkout@v2
      - name: Use Node
        uses: actions/setup-node@v1
        with:
          node-version: '14'
          registry-url: https://registry.npmjs.org/
      - name: Install dependencies
        run: yarn
      - name: Build
        run: yarn build
      - name: Publish New Version
        env:
          NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
        run: |
          git config --local user.email "myEmail"
          git config --local user.name "myUsername"
          yarn version --new-version ${{github.event.inputs.release}} --no-git-tag-version
          yarn publish --access public
          PACKAGE_VERSION=$(node -p "require('./package.json').version")
          git commit -a -m "v${PACKAGE_VERSION}"
          git push
Enter fullscreen mode Exit fullscreen mode

Add secret npm token

To run your action you need to add NPM_TOKEN environement variable.

Go to you npm account and generate an access token for CI :

Npm access token

Copy past this token in Github secret of your repository :
Github action secret

Now run your github action and take a coffe.

Trigger github action

Top comments (0)