I have an app that uses a core directory, and besides the core, I have different directories that contain classes that extend core classes and have slightly modified logic.
I got a file tree like below.
app
|-- core
| |-- x
| |-- y
| |-- z
| `-- plugins
| |-- xyz-helper.js
|
|-- slightly-modified-logic
| `-- plugins
| |-- xyz-helper.js
I want to use existing Webpack functionality to achieve something similar to a "theming" solution. You have a subtheme where you can override parent theme templates, if you don't override a specific template, it's gonna use the parent theme.
So, in my case, the ideal scenario would be:
1) Mount slightly-modified-logic
directory
2) Dependencies in core classes should be resolved using the mounted directory, if the mounted directory does not provide an implementation of its own, only then fall back to core classes themselves.
I checked NormalModuleReplacementPlugin
but that seems useful only if you wanna affect the entire build, I want the bundle to include everything, that or module chunk for each non-core directory that I load on demand.
The way I'm thinking of doing this is by building a resolve
map, assuming I can chain path custom aliases, and Webpack tries all of those before falling back to normal resolution. But how do I do that @ runtime? The decision to mount a different directory than core should be taken based on runtime parameters.
I only need some hints, thanks.
You can use Webpack dynamic imports. You can check the documentation on "Weback - Dynamic expressions in import()"
. A part of the modules path should be specified, for example if we have a themes
directory, we can load the corresponding theme plugins/code like so:
import(`themes/${themeName}/config.js`);
import(`themes/${themeName}/plugins/plugin.js`);
Assume we have a file structure:
themes
├─ themeA
│ └─ plugins
│ └─ plugin.js
└─ themeB
└─ plugins
└─ plugin.js
And the contents for each plugin.js
file:
// themeA/plugins/plugin.js
export const thePlugin = () => console.log('Plugin A');
// themeB/plugins/plugin.js
export const thePlugin = () => console.log('Plugin B');
We can use dynamic imports like this:
let theme = 'themeA';
import(`./themes/${theme}/plugins/plugin.js`).then(({ thePlugin }) => {
thePlugin();
});
theme = 'themeB';
import(`./themes/${theme}/plugins/plugin.js`).then(({ thePlugin }) => {
thePlugin();
});
And the output will be:
Plugin A
Plugin B
You can read a nice article about "Webpack and dynamic import".