Recently I had to build an NPM package in an environment that did not have any network access 1. Normally if you run npm install --offline the build would normally fail with the following error.
This happens because NPM’s cache is not hydrated.
However it is possible to build the package if it has a package-lock.json and if all of the dependencies specified in the lock file are placed into NPM’s cache before the build. This blog post outlines how to do that so a NPM package can be built and installed in an offline environment.
Example package
For this blog post I have setup a very basic NPM package with a single dependency on the chalk package. The package is composed of the following files.
The index.js contains:
The package.json contains:
The package-lock.json was generated by running npm i --package-lock-only.
Building offline with Docker
Setting up an offline build environment with Docker is straight forward with the following Dockerfile.
Then running docker build --network none . triggers a build without network access and returns the ENOTCACHED error.
Hydrating the cache
To overcome the ENOTCACHED dependency the chalk-5.2.0.tgz file needs to be already placed into the cache before the build starts. Assuming chalk-5.2.0.tgz is already available then using npm cache add before npm install -offline fixes the problem. The Dockerfile can be changed to:
By calling npm cache add on every dependency specified in the package-lock.json before the build, the build can occur offline.
Changing the entrypoint to /app/index.js shows the package was installed correctly.
Conclusion
It’s possible to build NPM packages in an offline environment so long as the package has a package-lock.json and all of the locked dependencies are added to the NPM cache prior to running npm install --offline. This enables building NPM packages in constrained environments using standard tooling.