Optional incompatible packages are still downloaded

cli
help-wanted
good-first-patch
priority:low
triaged

(Filipe Silva) #1

What I Wanted to Do

I wanted optional large incompatible optional packages to not be downloaded.

What Happened Instead

They were downloaded even though they were known to be incompatible, and didn’t end up in the final node_modules.

Reproduction Steps

There’s a repro in https://github.com/filipesilva/bazel-optional-dep-download.

git clone https://github.com/filipesilva/bazel-optional-dep-download
cd bazel-optional-dep-download
npm run test-npm

Details

The repro installs @bazel/bazel, which contains 3 optional dependencies with OS restrictions :

  • @bazel/bazel-linux_x64 containing "os": ["linux"]
  • @bazel/bazel-darwin_x64 containing "os":["linux"]
  • @bazel/bazel-win32_x64 containing "os": ["win32"]

Each of these platform specific packages contains a large (~160mb) binary.

The final installed node_modules contains only one of these packages, but through the verbose logs we can see that all three were downloaded:

npm http fetch GET 200 https://registry.npmjs.org/@bazel%2fbazel-linux_x64 1383ms
npm http fetch GET 200 https://registry.npmjs.org/@bazel%2fbazel-darwin_x64 1427ms
npm http fetch GET 200 https://registry.npmjs.org/@bazel%2fbazel-win32_x64 1439ms
// ...
npm http fetch GET 200 https://registry.npmjs.org/@bazel/bazel-linux_x64/-/bazel-linux_x64-0.18.0-rc4.tgz 6038ms
npm http fetch GET 200 https://registry.npmjs.org/@bazel/bazel-win32_x64/-/bazel-win32_x64-0.18.0-rc4.tgz 21486ms
npm http fetch GET 200 https://registry.npmjs.org/@bazel/bazel-darwin_x64/-/bazel-darwin_x64-0.18.0-rc4.tgz 25509ms

The first set of requests already contains the package.json data for the packages so it is already possible to know that the package is incompatible with the OS, and thus should be ignored since it is a optional.
There should be no need to download it.

Platform Info

$ npm --versions
{ 'bazel-optional-dep-download': '1.0.0',
  npm: '6.4.1',
  ares: '1.14.0',
  cldr: '33.1',
  http_parser: '2.8.0',
  icu: '62.1',
  modules: '64',
  napi: '3',
  nghttp2: '1.33.0',
  node: '10.10.0',
  openssl: '1.1.0i',
  tz: '2018e',
  unicode: '11.0',
  uv: '1.23.0',
  v8: '6.8.275.30-node.24',
  zlib: '1.2.11' }
$ node -p process.platform
win32

(Oluwafemi Sule) #2

This isn’t a documented behavior when optionalDependencies is specified in package.json
Sorry to bother you @zkat, is this a bug or a feature?
https://docs.npmjs.com/files/package.json#optionaldependencies