Auto Publish TypeScript Package with Semver to NPM

Introduction

When using packages, one often wonders about the general process of managing package development. Today, I encountered Matt Pocock’s Blazing Fast Tips: Publishing to NPM🔗 tutorial and implemented it, also publishing a TS package based on my previous needs: edit-element🔗.

1. Install TypeScript

  1. Initialize a new NPM package.
  2. Install the latest version of TypeScript.
  3. Initialize a basic TypeScript configuration file, which will generate a default tsconfig.json that can be modified as needed.
Terminal window
pnpm init
pnpm add typescript -D
npx tsc --init

Finally, you can directly execute tsc file location to transpile the .ts files into .js:

Terminal window
pnpm tsc foo.ts

2. Convert Module Format

The awkward part is that the JavaScript ecosystem has two module systems: CommonJS and ES Modules. Therefore, we use the tsup🔗 package to quickly bundle the ts files into the required format. After installation, set the script to be triggered in the NPM Scripts🔗 section of package.json.

package.json
"scripts": {
"build": "tsup index.ts --format cjs,esm --dts",
},

The setup is also very simple; just specify the location of the TS files and the types to convert, with the default output in the dist folder. After generating different types of package files, remember to label the files corresponding to different module systems.

package.json
{
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts"
}

3. CI Process

Now you can perfectly edit index.ts and push your package to NPM using tsup! However, the entire code release process is still not very smart. It’s best to perform a check and build on the code every time there is a code push. GitHub Actions🔗 can conveniently achieve this by creating a simple workflow file in .github/workflows:

ci.yml
name: CI
on:
push:
branches:
- '**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20.x
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm run lint && pnpm run build

4. Automate Semantic Versioning Releases with Changeset GitHub Actions

With the CI process in place, we can further consider how to automate the deployment process as well. Install @changesets/cli🔗 and add a new Workflow to automate using changesets/action🔗:

package.json
"scripts": {
"build": "tsup index.ts --format cjs,esm --dts",
"release": "pnpm run build && changeset publish",
},
publish.yml
name: Publish
on:
workflow_run:
workflows: [CI]
branches: [main]
types: [completed]
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: write
pull-requests: write
jobs:
publish:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20.x
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- name: Create Release Pull Request or Publish
id: changesets
uses: changesets/action@v1
with:
publish: pnpm run release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Regarding the environment variables that will be used:

  1. GITHUB_TOKEN - Grant necessary GitHub permissions by setting permissions🔗. This variable is preset.
  2. NPM_TOKEN - Log in to NPM > Access Tokens🔗 to set up a key for read and write access to your account, and place it in GitHub Env🔗.

Once set up, you can run npm run changeset anytime you want to change the project version and input the types and details of the package versions to be updated, which will automatically generate a temporary markdown file.

To push the version later, you can use npm run changeset version, which will automatically update the package version. After committing, the previously written Publish process will detect version differences and automatically deploy to NPM and GitHub Releases🔗.

Summary

If you prefer learning through videos, I recommend watching Matt Pocock’s Blazing Fast Tips: Publishing to NPM🔗 tutorial, but be aware that the package version is lower, and some adjustments are needed. The latest progress should be checked in the mattpocock/pkg-demo🔗 repository.

Through this tutorial, I also created my own package: edit-element🔗, and expanded it with additional testing processes and environments for reference.

Further Reading