Publishing Packages
How to publish monorepo packages to npm using the dual-mode export strategy.
This guide explains how to publish packages from the monorepo to npm using the dual-mode export strategy.
Overview
Our packages use a dual-mode export strategy:
- Development mode: Exports point to
src/for fast local development without requiring builds - Publishing mode: Exports point to
dist/for npm consumers who need built artifacts
This allows:
- ✅ Fast local development (no build step needed)
- ✅ Next.js can transpile
src/directly viatranspilePackages - ✅ Clean
dist/-only packages for npm publishing - ✅ Proper TypeScript types in both modes
How It Works
The publishing process uses npm lifecycle hooks:
prepack Hook
Runs before pnpm pack or pnpm publish:
- Builds the package (
pnpm buildruns first via the prepack script) - Stores original
package.jsonexports/main/types in.package-originals.json - Switches
exports,main, andtypesto point todist/ - Sets
files: ["dist"]to ensure only built files are included
postpack Hook
Runs after packing:
- Reads the stored originals from
.package-originals.json - Restores the original
package.jsonconfiguration - Removes the temporary
.package-originals.jsonfile
Package Configuration
Packages that use these scripts should have:
Development exports (in package.json):
{
"exports": {
".": {
"types": "./src/index.ts",
"import": "./src/index.ts"
}
}
}Publishing exports (automatically set by prepare-publish.mjs):
{
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": ["dist"]
}Usage
These scripts are automatically invoked via npm/pnpm lifecycle hooks in package.json:
{
"scripts": {
"prepack": "pnpm build && node ../../scripts/prepare-publish.mjs",
"postpack": "node ../../scripts/restore-publish.mjs"
}
}Publishing a Package
- Build and test your package locally
- Update version in
package.json(or usepnpm version) - Publish:
cd packages/your-package pnpm publish
The prepack hook will automatically:
- Build the package
- Switch exports to
dist/ - Create the tarball
The postpack hook will automatically:
- Restore the original
package.json - Clean up temporary files
Scripts Reference
The publishing scripts (prepare-publish.mjs and restore-publish.mjs) are located in the /scripts directory.
Notes
- The scripts use
process.cwd()to find the package'spackage.json(they run from within each package directory) - If
.package-originals.jsondoesn't exist,restore-publish.mjsexits gracefully (useful for first-time runs) - These scripts are only needed for packages that will be published to npm
- Private workspace-only packages don't need these scripts