Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent NPM install from removing symlinked node_modules directory

Tags:

npm

symlink

I use a deployment service to push my LEMP app's code; I'm on Ubuntu 20.04 / AWS. I've installed Node via NVM and am using Node v19.6.1 & NPM v9.4.0

  • My deployment process uses symlinking to map a /current/ directory to the latest release.
  • I also have a /shared/ directory that stays in place for assets that either A) don't need to change B) should say centralized.
  • The shared directory houses things like /node_modules/; the primary reason for doing things like this is to prevent a bunch of releases having duplicated /node_modules/ folders taking up space in different release directories.

  1. I've run the following to create my symlink sudo ln -sv /var/www/mysite/html/shared/assets/node_modules /var/www/mysite/html/current/assets/node_modules

  2. I see the symlink when I do /var/www/mysite/html/current/assets/ && ls -la

  3. When I run the following, npm removes my symlink cd /var/www/mysite/html/current/assets/ && npm i

Specifically running npm i starts by literally saying it's removing my symlink; I want it to keep the symlink...but install the files in my symlink destination.

npm WARN reify Removing non-directory /var/www/mysite/html/releases/####/assets/node_modules

In the past, I'm pretty sure that I've had my node_modules directory symlinked, have been able to run npm i in the directory where the symlink exists, and my files get installed in the symlink destination folder.

I've also tried npm link

  1. From within my shared directory, I've created the symlink for my package.json file (if I don't do this npm link outputs an error) sudo ln -sv /var/www/mysite/html/current/assets/package.json /var/www/mysite/html/shared/assets/node_modules/package.json

  2. Then I run cd /var/www/mysite/html/shared/assets/node_modules/ && npm link Lastly I run cd /var/www/mysite/html/current/assets/ <my-project-name>; this seems like it's running npm, but this doesn't seem to actually install anything.

As a workaround I've just done:

  1. Install npm, move it, and then symlink it

cd /var/www/mysite/html/current/assets/ && npm i sudo mv /var/www/mysite/html/current/assets/node_modules /var/www/mysite/html/shared/assets/node_modules sudo ln -sv /var/www/mysite/html/shared/assets/node_modules /var/www/mysite/html/current/assets/node_modules

...but that just feels wrong / weird

My questions

  1. Has removing the node_modules folder / symlink something that is in newer versions of npm that wasn't in older versions?

  2. How can I: A) symlink my node_modules folder B) keep my symlink when using npm C) make sure that my files get installed into the symlink destination directory?

  3. Is there a best-practice / something obvious here that I'm missing?

like image 875
Ryan Dorn Avatar asked Oct 24 '25 16:10

Ryan Dorn


1 Answers

Removing node_modules if it's a symlink and replacing it with a directory is behaviour that was introduced in npm 7.20.6 to prevent a certain class of security vulnerabilities.

Based on the discussion in the npm github issue there are no great work-arounds or suitable configuration possible for this behaviour. Using the --force argument has too many other drawbacks, notably re-downloading all resources always.

To address your specific requirements, namely saving space usually wasted by multiple release directories, consider implementing your normal node_modules symlink approach with yarn, or switch to pnpm, which will by default use hardlinks / reflinks to de-duplicate between all of your projects.

I have just confirmed that both the latest yarn classic (1.22.19) and pnpm 8.6.0 preserve one's node_modules symlink.

like image 73
Charl Botha Avatar answered Oct 27 '25 09:10

Charl Botha