Create and publish npm module library with esbuild typescript and react Type: blog post Language: en-US Canonical URL: https://simonboisset.com/en/blog/publish-npm-library-with-esbuild Published: October 2, 2022 Summary: 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 ar... 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: https://github.com/simonboisset/remix-feature-routes for an example of this post. Initialization Create your folder project and initialize it. yarn init Your package.json file should be defined : { "name": "my-react-library", "version": "1.0.0" } Now we will install our dependencies. Install dev dependencies yarn add -D react react-dom typescript @types/react @types/react-dom Don't forget to add react as a peer dependency if you are writing a react library with hooks or components. "peerDependencies": { "react": ">=16" }, 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" } } 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 Hello word ; }; 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 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)); Add a build commande And finally add a script in your package.json : "scripts": { "build": "rm -rf dist && node esbuild.js && tsc" }, Now you can run : yarn build Npm publish Before publishing you need to be authenticated: https://docs.npmjs.com/creating-a-new-npm-user-account Add these lines to your package.json : "main": "dist/index.js", "files": [ "dist" ], Then publish it : npm publish 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: workflowdispatch: 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: NODEAUTHTOKEN: ${{secrets.NPMTOKEN}} 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 PACKAGEVERSION=$(node -p "require('./package.json').version") git commit -a -m "v${PACKAGEVERSION}" git push Add secret npm token To run your action you need to add NPMTOKEN environement variable. Go to you npm account and generate an access token for CI : Npm access token: https://directus.services.lezo.dev/assets/213a95c1-1ce9-45b4-bc5c-bd23c8ea2dca Copy past this token in Github secret of your repository : Github action secret: https://directus.services.lezo.dev/assets/9bc983ff-e328-475b-ae4c-37799b7ee0f3 Now run your github action and take a coffe. Trigger github action: https://directus.services.lezo.dev/assets/cb86ea78-a42a-43a3-b068-f513139573b7 --- I'm Simon Boisset, freelance fullstack developer. I mainly work with React, React Native and Node.js. I'm available for development or consulting missions. Feel free to contact me on my website: https://simonboisset.com. Related links Blog index: https://simonboisset.com/en/blog Website: https://simonboisset.com/en