How to build node package without internet
A way to vendor NPM dependencies
If you have your CI/CD pipeline for anything made in your company, it must satisfy following properties to keep everyone sane:
- The same commit should build into the same binary
- There should be a process of building a binary from a source code on local infrastructure only (no internet access at all).
If your build process uses internet at a build time, you can not have neither #1 nor #2. Just imagine NPMJS company been sold to some malicious red company with ferocious lawyers. Use NPM Enterprise! Buy subscription! No access for those without money.
Or, imagine a less onerous scenario: a small quarrel between NPMJS with CDN provider for better prices, with outage of npm repository for …let’s say four days. Do you need to make a new release ASAP? No access to packages? No internet?
So, if you want to have autonomy, you need to have all dependencies locally. Here I describe how to do it with minimal struggle (and at a half price of node_packages size).
How to have offline npm cache
- For example purposes we use /work/my_web as a project directory. There is a
/work/my_web/.git
,/work/my_web/src
etc. - Set up a project-local configuration. If you you already have it, update it, if not, create a file
/work/my_web/.npmrc
:
cache=.npm_cache
3. add node_packages
into .gitignore
file. Commit both changes into git.
4. Run npm ci
, or, if you’re using older version:
rm -rf node_packages
npm install
You will have a hefty download, but that’s ok.
5. Commit .npm_cache
into your repository.
That’s all.
If you clone this repository, disable network access, you still be able to build your package:
npm install #or npm ci
ng build --prod # or any other webpack run
Moreover (this is linux specific), you can check if you can do this in offline:
firejail --net=none npm install
firejail --net=none ng build --prod
This simple trick allow you to have you repository to contain everything you need for offline build.
How to update
If you decide to change something in your dependencies, you need to do this:
rm -r .npm_cache
npm install
git add package.json package-lock.json .npm_cache
It’s very important to save package-lock.json
in the same commit as .npm_cache
. This is guaranteed you can checkout this commit at any time in the future and to have exact match between lock and it’s cache.
rm
for .nmp_cache
just help to keep it smaller.
Afterword
Vendoring is bad. Just look at the size of your .npm_cache
. Evenso, it’s better to have vendored bloat, then slim ‘something new from internets on each build’.
Leftpad story forced Npmjs to forbid version change and package removal. Nevertheless, this does not fix the problem of ‘internet dependency at build time’. If you have transient internet at build time, you have transient builds, which are mostly ok, except when not.
Next step
I do deb/dpkg packaging of front-ends. I know Dorker fans are appalled, but I knew what I do, and why.