Substitute synchronous (Webpack) bundled ESM client code on the server side (Node) based on feature flag

Given:

moduleA.mjs,
moduleA_FeatureFlag1.mjs,
moduleA_FeatureFlag2.mjs,

Where:
no modules expose an async export

I’d like to substitute moduleA.mjs from my node server at runtime (or at least at pod startup time) based on a feature flag stored in an environment variable. For example, I would switch moduleA.mjs for moduleA_FeatureFlag1.mjs on the server side if environment variable GLOBAL_FEATURE_FLAGS=FeatureFlag1

In webpack, you can easily do this if you have async code by using a const module = await import(<name of module>); in your code base.

However, the idea here is to allow developers to quickly and arbitrarily substitute new feature flag specific code in the application by copying existing modules (which might have synchronous interfaces) and renaming the copy with the feature flag (maintaining the same exports obviously). I don’t want people to have to add redirection logic in the existing modules to do this. The whole idea here is to keep the existing, tested logic unchanged so there are fewer opportunities to introduce regressions in the non-feature flag code.

This copying and renaming happens before the code is webpack bundled for production, so I could use webpack to do this. I just don’t know how (without using async import();).

Because this is going to be happening all the time (there may be dozens of feature flags at a time), it will be too much ceremony to separate the code into its own bundled library for every feature flag – unless there is some way to make this transparent to the developer by automating the process at bundle time.

Also, this is a large code base (i.e. slow to build) and there may be any number of these files with feature flag substitutions, so building every possible combination of them is probably a bad idea.