Local package development
Test from a real consumer
Install the packed artifact in another project so source-tree shortcuts cannot hide packaging mistakes.
Tests inside the package repo can pass while the published tarball is broken. Relative imports into src/ hide missing files, wrong exports, and stale dist/ output.
I never trust a library until I install the packed artifact the way npm users will.
Pack and install into a fixture app
From the package root:
npm run build
npm pack
That creates acme-slugify-title-0.1.0.tgz. In a separate directory:
mkdir /tmp/slugify-consumer && cd /tmp/slugify-consumer
npm init -y
npm install /path/to/acme-slugify-title-0.1.0.tgz
Create smoke.mjs:
import { slugifyTitle } from '@acme/slugify-title'
console.log(slugifyTitle('Hello World!'))
Run it:
node smoke.mjs
Expected output:
hello-world
If you see Cannot find module '@acme/slugify-title' or an exports error, the packaging metadata is wrong, not your unit tests.
Test both module systems you claim to support
If exports lists import and require, add a CommonJS smoke file:
const { slugifyTitle } = require('@acme/slugify-title')
console.log(slugifyTitle('Hello World!'))
Run it with node smoke.cjs. TypeScript consumers deserve a fixture too: import the package in a .ts file and run tsc --noEmit against the installed types.
Why npm link is not enough
npm link symlinks your working tree. It skips tarball contents, files filtering, and prepack hooks. Use link for fast iteration, then always verify with npm pack before release.
Keep the fixture script in your repo under fixtures/esm-consumer/ so CI can run the same smoke test you run locally.
A hostile check worth running once
Pack the package, then delete dist/index.js from the tarball contents only in your mind: would the consumer error mention exports or a missing file? Now actually break exports in package.json, repack, and install. Node should fail with a subpath or module resolution error. Fix the map, repack, and confirm the smoke test passes again.
That exercise takes ten minutes and saves hours when you rename build outputs later.
Lesson completed