`npm link package@version` runs postinstall scripts instead of just symlinking


(Michael Martin Smucker) #1

What I Wanted to Do

I want to create a global installation of bs-platform@4.0.6 and symlink that library into all repositories that depend on it. Mostly I want to do this because bs-platform has a postinstall script that builds an OCaml compiler, which is slow (~1 minute), and I don’t want to re-run that for each new project, or each time I delete and re-install node_modules.

I want to put this link step in a preinstall script, so that everyone on my team shares this same experience. I also want to lock down the version to 4.0.6.

I have bs-platform installed in my global node_modules:

$ npm ls -g bs-platform
└── bs-platform@4.0.6

Running npm link bs-platform simply creates the link and exits immediately. :+1:

However, I want to make sure everyone on my team is using the same version of bs-platform, and a simple npm link will happily link up global versions, even if they differ from the version specified in package.json. To work around this, I tried changing the link command to npm link bs-platform@4.0.6 (which should be supported, according to the limited docs).

What Happened Instead

Instead of simply symlinking to the already-installed global bs-platform@4.0.6, npm appears to do a clean global install every time, rebuilding the OCaml compiler.

Reproduction Steps

  1. Create an empty project, initialized with a package.json
  2. npm install --save bs-platform@4.0.6
  3. Edit the package.json to allow exactly 4.0.6
  4. npm i -g bs-platform@4.0.6
  5. rm -rf node_modules
  6. npm link bs-platform # works as expected
  7. rm -rf node_modules
  8. npm link bs-platform@4.0.6 # does a clean install with a long postinstall step

Platform Info

$ npm --versions

{ home_bay_zapier_cli: '3.7.1',
  npm: '6.6.0',
  ares: '1.14.0',
  cldr: '33.0',
  http_parser: '2.8.0',
  icu: '61.1',
  modules: '64',
  napi: '3',
  nghttp2: '1.32.0',
  node: '10.6.0',
  openssl: '1.1.0h',
  tz: '2018c',
  unicode: '10.0',
  uv: '1.21.0',
  v8: '',
  zlib: '1.2.11' }

$ node -p process.platform

(Eugene Dorofeyev) #2

I’m experiencing the same issue.

The recent update of Terser toolkit 3.16.0 broke terser-webpack-plugin 1.2.1:

I am building browser extension which is then uploaded for a review, so in my building process I need to specify the exact version of packages which should be installed later on reviewer’s computer.

I install packages globally since they’re used in multiple places (browser extension consists of 4 separated components, each built individually), to reduce build time.

I can manually rollback to terser@3.14:

npm un webpack terser-webpack-plugin terser -g
npm i terser@3.14 webpack@4.28.4 terser-webpack-plugin@1.2.1 --exact-versions -g

But when I’m linking against the exact version of webpack or terser-webpack-plugin I previously installed globally:

npm link webpack@4.28.4
npm link terser-webpack-plugin@1.2.1

It looks like NPM performs global installation of packages that are already installed, causing terser to be updated to 3.16.0 again, and thus failing the build.

(Eugene Dorofeyev) #3

Same issue appears once again.

ajv was updated to version 6.9.0, and caused file-loader to stop working.

I my project I first do

npm link ajv@6.7.0


npm link file-loader@3.0.1

This causes ajv to get updated to the latest version while I have just linked against 6.7.0, and caused file-loader stop working because of bug in ajv@6.9.0.

I don’t see here https://docs.npmjs.com/cli/link.html any mention that npm link downloads and installs latest version of packages from repository. It is supposed only to, quote “create a symbolic link from globally-installed package-name to node_modules/ of the current folder.”