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.

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