2

We have a library that is traditionally client-side only. It uses HTTP Request (or several other dependency libraries) to make REST calls. When using the library, user will initialize with a particular request provider and off they go.

We use webpack in our examples to utilize our library.

It is now extended it to use node-fetch, so if someone wants to use it from nodejs that's supported too.

For people using webpack, webpack is now attempting to pack node-fetch and the require call is failing in the browser. We can get around this with setting an external

"externals" : {
    "node-fetch": "{}"
}

Is there a way to define our library so that if the consumer is using webpack target: web, it'd skip the require check for node-fetch? And similarly, if the consumer is using webpack target: nodejs - it needs to include the node-fetch component.

The project in question is https://github.com/OfficeDev/PnP-JS-Core

John Liu
  • 1,334
  • 1
  • 11
  • 16

2 Answers2

2

Thanks for reporting this. So according to This commit and conversation linked to it, the automatic module resolution field (also known as a described-resolve to the webpack resolver instance) changes based on what your target is.

By default, when target is node in your webpack build, resolution in package.json field will default to the main field else, browser field takes priority by default.

More reference https://github.com/webpack/webpack/issues/151

Sean Larkin
  • 6,290
  • 1
  • 28
  • 43
  • 1
    Our package.json update PR was fixed and issue closed. Thanks :) I leave this comment here as an example of what it should look like. https://github.com/OfficeDev/PnP-JS-Core/blob/master/package.json and here is the link to the 'spec' https://github.com/defunctzombie/package-browser-field-spec – John Liu Sep 05 '16 at 06:30
1

The links provided in the accepted answer & comment show how to do this, so +1 to those, but just to surface it directly here

Is there a way to define our library so that if the consumer is using webpack target: web, it'd skip the require check for node-fetch

Yes. In the library's package.json, add a browser field with the following

"browser": {
  "node-fetch": false
}

This provides a hint to webpack and other bundlers that the the node-fetch module should be ignored - i.e. do not even attempt to include it in the bundle - when the target is web. When the target is node, it will be included.


Note that the above relies on the code in the client bundle never using node-fetch. In that sense it can be considered unsafe, because there is no compile-time guarantee of this, and if it happens, it will just error and probably crash your client. If you're absolutely sure it can never be used client-side, though, this is the simplest way to get this done.

For more safety - i.e. if you want the client code to only warn if you try to use node-fetch - you also have the option of providing a shim to the module that the client bundle can include instead, and for instance just log a warning in the shim implementation if it gets used. You do this in the same way, just by providing a path to the shim module instead of false

"browser": {
  "node-fetch": "./shims/node-fetch.js"
}
davnicwil
  • 28,487
  • 16
  • 107
  • 123