npm login# Publish normally
npm publish
# Publish a scoped package in public (When you want to publish under your own name)
npm publish --access=public
# Check who's currently logged in
npm whoamiMy recommended approach. Based on Matt Pockock as well. I use Bun btw, but still applicable for PNPM (if you're smart enough to replace the CI stuff, I put labels on them, should be easy).
Tools you need:
- TSUP - for bundling
- Changesets - for auto version bumps & changelogs
- GitHub Workflows - for auto test and publish
- an NPM account - where you'll publish
# 1. Install on your npm package (If monorepo, install for every package)
bun add -D tsup- Make the
tsup.config.ts.
import { defineConfig } from 'tsup';
export default defineConfig({
entry: ['src/index.tsx'],
outDir: 'dist',
format: ['cjs', 'esm'],
dts: true,
splitting: true,
sourcemap: true,
clean: true,
});- Make your build and lint scripts
"lint": "tsc" # just a suggestion
"build": "tsup" # this emits `dist/index.js`, `dist/index.d.ts` and `dist/index.mjs` (sometimes)- Set your
package.json. (If monorepo, put in every package)
"private": false,
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js", # can be ./dist/index.mjs if your build emits it.
"types": "./dist/index.d.ts",
"files": ["dist"]# 1. Install in your project (If monorepo, just install in root. Only needed once)
bun add -D @changesets/cli
bun add -D @changesets/changelog-github # not necessary but nice to have for changelogs
# 2. Initialize changesets
bun changeset init # or pnpm changeset init
# >> This should make .changeset/config.json and README.md
# 3. Go to .changeset/config.json and change `"access": "restricted",` to "public".
# 4. Make these package.json scripts (for CI-purposes)
# will run on `main.yml` on all branches
"ci": "bun lint && bun run build"
# will run via `publish.yml` on `main` branch (NOTE: Make sure the name is not 'publish' because it will run recursively.
# Because changeset publish runs `npm publish` which calls prepublish and publish again, yes weird. Don't do it.
"publish-ci": "bun lint && bun run build && changeset publish"
# 5. Make your changes...
# 6. COMMAND you'll regularly use:
bun changeset # You will do this whenever you want to make a release/version bump. Demonstrated below later.You only need two main.yml and publish.yml
# .github/workflows/main.yml - Purpose: Just to check/test your codebase.
# I got this from Matt Pockock
# https://www.youtube.com/watch?v=eh89VE3Mk5g
name: CI
on:
push:
branches:
- '**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2 # replace with node + pnpm if you want.
- run: bun install --frozen-lockfile # replace if you want.
- run: bun run ci # replace if you want.# .github/workflows/publish.yml - Purpose: Does two things, Create a "Release PR" or Publish to NPM
# I got this from Matt Pockock
# https://www.youtube.com/watch?v=eh89VE3Mk5g
name: Publish
on:
push:
branches:
- 'main'
# Publish workflows don't happen at the same time.
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- run: bun install --frozen-lockfile
- run: bun run build
- name: Create Release Pull Request or Publish
id: changesets
uses: changesets/action@v1
with:
publish: bun run publish-ci
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} # TAKE NOTE, you have to generate this in NPM
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # You DON'T need to generate this, it's automatic by GitHub Workflows.- Generate an Access Token
- Go to NPM > Access Tokens > Generate New Token. (name it if you want). Make sure to copy it!
- Then go to GitHub > Settings > Secrets and variables > Actions
- Add a new repository secret and name it
NPM_TOKEN. Make sure to paste your ACCESS TOKEN here.
- In NPM, make sure to turn off 2FA for writes. So publish works in CI without
--otp.- Go to NPM > Account > Modify 2FA > Additional Options
- Require two-factor authentication for write actions
- Go to NPM > Account > Modify 2FA > Additional Options
- Last gotchas with GitHub, make sure to do this:
- In GitHub, go to GitHub > Settings > Actions > General and set:
- Workflow Permissions: Read and write permissions
- Allow GitHub Actions to create and approve pull requests
- In GitHub, go to GitHub > Settings > Actions > General and set:
The instructions above just taught you how to setup the automations, but what's the routine thing you'll do as a dev and how do your automations interact with you?
How it flows:
- Make your changes (as usual).
- If you want these changes set for a release, just run
bun changeset.- Just follow the instructions of choosing
major,minor,patch - Then write a summary (This will be used in the changelog).
- After this, it emits files in
.changelog/<some-jibberish>.md
- Just follow the instructions of choosing
- If you're good, just commit to
mainand push. (Or make a PR tomain). - After that
publish.ymlwill trigger, it will know that you have<some-jibberish>.mdand automatically creates a Release PR.- This PR removes
<some-jibberish>.mdand bumps the package version.
- This PR removes
- If you want to Publish it to NPM, find the PR, and press Merge.
- After it merges to
main,publish.ymlwill run again, but this time it notices that there are no pending changesets, hence it will just publish automatically!
Hope that helps!