I develop a library that works in the browser and in Node.js. When executed in Node.js, the library depends on a module that is not needed in the browser. My library's code simply performs a simple feature detection test and, if needed, the extra module is imported with require
. Everything works fine.
The problem arises when someone uses my library in a project that relies on Webpack. In this case, during compilation, Webpack always bundles the module even for browser-oriented projects where the module is not needed.
Is there a way for me, as a library developer, to prevent Webpack from bundling a module when the bundle will be run in a browser?
The only thing I can think of is distributing two versions of my library which I would really like to avoid.
I came out with my own solution. It's a bit hackish but it solves the problem without having to ask my users to customize their Webpack configuration.
The idea is simply to hide the import from Webpack. In the CommonJS version, this is what I'm using:
if (isNode) {
let mod;
eval('mod = require("some_module")');
}
In the ESM version (which is used when "type": "module"
is set in the package.json
file), I'm using this:
if (isNode) {
let mod = await Object.getPrototypeOf(async function() {}).constructor(`
mod = await import("some_module");
return mod.default;
`)();
}
When Webpack compiles the code, it ignores the imports because they are hidden in strings. So, when the code runs in the browser, we simply ignore that code block and when it is run in Node.js, the import is performed dynamically.