Automatically importing a util module into every file in NodeJS

37 Views Asked by At

Is there a way to automatically import a module into every file without using a global variable? In Webpack, I can use ProvidePlugin which automatically injects import util from './util.js' into every file that references util.

E.g.

plugins: [
  new webpack.ProvidePlugin({
    'util': './util.js',
  })
],

My goal is to avoid the grief of having to add import definition lines for commonly used utility or configuration modules.

Thanks

1

There are 1 best solutions below

1
adsy On

When you use something like ProvidePlugin in the front-end world you are, by all intents and purposes from a semantic and useability perspective, providing a global. It suffers from almost all the disadvantages using a global does. You gained pretty much nothing from a code quality point of view over a global.

If you need/want a global, use one. If you really want this then that is the first-class language support that exists to solve this problem.

You could probably use custom node ESM loaders to achieve it, but as above, that's imitating global semantics. You could also start compiling your JS code with something like babel. Which on the back end, is like cracking a nut with a sledgehammer.

I would recommend against this way of thinking entirely (sorry if this sounds like a party pooper!). Removing the burden of having the import lines might seem attractive, but actually, If I were a new dev in this codebase I would wonder what on earth is happening. It breaks developers' expectations. The consistency and expectation of that consistency massively outweigh any saving by not having that line, which is usually inserted seamlessly & automatically as a matter of course by the IDE anyway. You therefore pretty much never see tricks like this in node code. There's little reason to run a bundler-like tool like webpack on back-end code, or even transpilers, outside of TypeScript (which isn't general purpose enough as a standalone build tool to solve this type of problem, but ts-morph is noteworthy). So certain expectations have arisen from that mindset.

Not to mention that if you went down the "inject" route it will play havoc with linting tools, IDE IntelliSense and other static analysis tooling.

It also makes human understanding of scope more ambiguous. If another variable happens to use the same name (say, a function param), it becomes unclear what is being referenced, to both humans and most of all to the IDE. Sure this may have a hard and direct answer, but this isn't the kind of thing you introduce willingly.

Even worse, you'd then have to ensure compatibility with other software like testing tools, or even develop parallel solutions for those tools just to support this Frankenstein setup. Suddenly there's more code & complexity to support not just doing the import than if the import was there anyway.

It's also a possible sign of a code architecture problem. If you need this everywhere then perhaps that is a sign that actually, this thing should be attached to certain prototypes/classes at a deeper level (so in core places) such that is available locally.

For example, classes/objects may provide a this.logger or something along those lines. This also promotes better decoupling.