When working on multiple interdependent NPM packages across projects, testing a new version before publishing is essential.
At Prisma Media, we maintain several packages on our private NPM registry, used directly on our websites. While each package comes with a standalone demo, we regularly need to validate development versions in real environments.
Understanding npm pack
Running npm pack builds your package locally and generates a .tgz archive identical to what would be published with npm publish. The archive is created in the current directory and includes only the files defined in the files field of your package.json or filtered by .npmignore.
It's also a convenient way to verify what your package will actually ship before publishing. Inspecting the generated archive helps ensure that only the expected files are included.
Testing options
Developers have a few options to test packages locally:
-
Local linking:
npm linkworks if both the package and consuming project are cloned locally -
Preview or shared environments:
npm linkfails here. Other options include:- Publishing a tagged version (like
beta), it requires deployment to the registry - Using
npm pack, it generates the.tgzarchive that would be published, without touching the registry
- Publishing a tagged version (like
We chose npm pack for its simplicity and safety. It allows developers and product teams to test new versions in local or preview environments, without affecting production workflows.
Implementation
Our package pipelines follow a standard sequence: install, build, test, pack and finally deploy.
For details on our reusable GitLab CI template you can read
The npm pack job is manual. When a developer needs a dev version:
- Navigate to the latest pipeline of the merge request
- Trigger the
npm-packjob - The job runs and uploads the TGZ as an artifact
- Install and test locally:
- Download and extract the artifact
- Install the TGZ in your project:
npm install <path_to_tgz_file>
- This replaces the version from the registry with the local TGZ version. Example diff:
- "player": "1.0.0"
+ "player": "file:player-1.1.0.tgz"
- Commit the TGZ file to your branch if you plan to deploy a preview
- Once committed, the CI will install the TGZ
GitLab CI template
Here is a simplified .gitlab-ci.yml template for the npm-pack job:
npm-pack:
variables:
PACKAGES_DIR: 'npm-pack-packages'
image: node:22-alpine
script:
- mkdir $PACKAGES_DIR
- PACKAGE_TGZ=$(npm pack)
- mv "$PACKAGE_TGZ" $PACKAGES_DIR
artifacts:
paths:
- $PACKAGES_DIR
when: manual
This job generates the TGZ locally and stores it as an artifact. The file can then be installed for local or preview testing.
For the GitHub Actions equivalent
Discover npm-pack workflow examples on GitHub
Advantages
- Developers can test packages locally without publishing
- The TGZ can be versioned in the dev branch, allowing CI to install it on preview environments
- Product teams can validate features before merging
⚠️ Remember: TGZ files are for development and preview only, never for production.
Key points
-
npm packreplacesnpm linkfor shared or CI environments - When switching back to a registry version, always run
npm uninstall <package>before reinstalling - Version TGZ files only for temporary testing; never use them in production
- CI pipelines can safely produce TGZ artifacts for local or preview testing
- Manual triggering keeps pipelines efficient
Conclusion
Using npm pack to test packages locally or in preview environments simplifies cross-project development. It sits between local linking and full registry publishing, giving developers and product teams a faster way to validate changes.
By integrating this workflow into CI, we can safely validate packages, maintain developer productivity and ensure quality before official publication.
The complete example is available on GitHub for you to try out! 🧑💻

Top comments (0)