defunctzombie / package-browser-field-spec

Spec document for the 'browser' field in package.json

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Impossible to implement safely with deduplicated dependencies?

joepie91 opened this issue · comments

According to the specification:

If a module you depend on already includes a browser field, then you don't have to do anything special. Whenever you require that module, the bundler SHOULD use the hint provided by the module.

... however, would this even be possible when using deduplicated dependencies, eg. when using NPM 3 or after manually deduplicating in NPM 2?

The specification is not very explicit about how this is to be implemented, but I can see three possible approaches:

  1. Every browser field specified by every package is applied globally to all packages (including to dependencies that are not its own) from the moment it is encountered. This creates potentially unsafe global state, and might lead to weird bugs.
  2. The browser field in a module's package.json only applies to its dependencies. However, this is not possible when deduplicated - there might only be one copy of a specific subdependency for two different dependencies (it might not even be in the module's node_modules folder!), and only one of them might want to override the require. Again, global contamination.
  3. The browser field in a module's package.json only applies to immediate dependencies, when required from that module's code. This means modules can no longer be cached (posing a possibly severe performance issue), "dependency tracking" logic has to be introduced, and it's not possible to forcibly override a subdependency without cooperation of the author of the 'higher-level' dependency. This does not seem workable either.

Can you see any way in which it would be viable to allow a module to specify a browser field? This seems like fairly important functionality (eg. Webpack's approach of "copy this to your webpack configuration if you use this module" is not very sustainabble), but I'm struggling to see a way in which this is actually possible.

This is actually very simple, the problem here is that deduping disrupts the structure of dependencies. If you are processing a project/file you just have to make sure to keep the file the request came from and use it's manifest and the browser field before processing the require.

I implemented this in require in this commit for anyone interested