Require a set of modules based on the DefinePlugin constant

I am trying to create a web application using Webpack, and I came across a wall with a certain part of the design - I hope someone here will have experience with similar material (or enough to know to tell me I'm doing it completely wrong)!

Basically, we have an Angular dashboard application that consists of a β€œshell” (common user interface, session management services, etc.) and a set of modules (stand-alone sections of the application that can be connected to the shell). The difficult point is that this application will be distributed among several clients, each of which will need a different set of modules, and it will require slightly different configuration parameters.

I already did this with DefinePlugin to load into the JSON configuration file as a constant during build:

 const envConfig = require(`./config/${yargs.argv.env || "dev"}`); ... new webpack.DefinePlugin({ __ENV__: Object.keys(envConfig).reduce((obj, key) => { obj[key] = JSON.stringify(envConfig[key]); return obj; }, {}) }) 

Then I tried to use a dynamic requirement to include only the specified modules, for example:

 __ENV__.modules.map((id) => require(`./modules/${id}/index.ts`).default) 

This kind of work - the right modules load, but Webpack does not understand that __ENV__ will never change at run time, so the assembly file itself includes all modules that are disabled and enabled. Obviously, this would increase the file size without the need for clients who need only one module, so I'm not very happy with it.

So, to reduce it to a simple question - is there an easy way to load a specific set of modules based on the DefinePlugin constant (or is there an alternative way to achieve what I'm trying to achieve)? I feel that there is something obvious that I must miss.

+2
source share
2 answers

You can configure resolve.alias and configure this for each client. This will give you the setting you want.

+1
source

I came up with a decent (?) Solution to this problem after taking bebraw advice - I thought that I would post it as an additional answer if someone is faced with the same problem or wants to implement something similar. I use TypeScript, but the same approach probably works fine in JavaScript with or without ES6.

Basically, now I have a directory called config in my src that contains a subdirectory for each client, for example:

 config β”œβ”€β”€ dev β”œβ”€β”€ cust1 └── cust2 

Each of them contains an info.ts file that exports constants, such as REST endpoint URLs:

 export default { name: "Company Name", server: "http://localhost:8810", service: "ServiceName" } 

And the modules.ts file, which exports an array of modules to pass into my load function of the boot application:

 import util from "../../modules/util"; import session from "../../modules/session"; import shell from "../../modules/shell"; import stock from "../../modules/stock"; export default [ util, session, shell, stock, ]; 

They should be separate - my original implementation had one .ts file for each configuration, but that meant that I ran into a cyclical dependency when I tried to import constants from modules.

Then I just added resolve.alias based on the command line argument:

 alias: { "config": path.join(__dirname, `src/config/${yargs.argv.env || "dev"}/`) } 

Now I can disable that config/info and config/modules refer only to a call:

 webpack --env dev webpack --env cust1 webpack --env cust2 

I still need to see how it works in practice, and perhaps clarify the interface for different exhibits, but as a starting point I still like it!

+1
source

All Articles