In need of a collection of modules determined by a DefinePlugin constant

Currently, I am in the process of constructing a web application utilizing Webpack. However, I have encountered a challenge with a particular aspect of the design - hopefully someone in this forum has experience in similar tasks (or possesses enough knowledge to inform me if I am on the wrong path)!

Essentially, we are developing an Angular dashboard application that comprises a 'shell' (the standard user interface, session management services, etc.) and multiple modules (self-contained segments of the app that can be attached to the shell). The complexity arises from the fact that this application will be deployed to various clients, each requesting a distinct set of modules along with slightly different configuration options.

To date, I have managed to make progress by using DefinePlugin to load a JSON config file as a constant during build time:

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;
    }, {})
})

I then attempted to utilize dynamic requiring to include only the specified modules, like this:

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

While this approach did work to some extent - loading the correct modules, it had a drawback. Webpack does not recognize that __ENV__ remains constant at runtime. Consequently, the build file contains all modules, even those that are disabled. This would unnecessarily increase the file size for clients who only need a single module, which is not ideal.

Therefore, my question is simple - Is there a straightforward method to load a specific set of modules based on a constant defined by DefinePlugin (or is there an alternative way to accomplish my objective)? It seems like there's something obvious that I might be overlooking.

Answer №1

To achieve the desired setup, consider implementing a resolve.alias and customizing it for each individual customer.

Answer №2

After receiving some helpful advice from bebraw, I managed to come up with a solution to this issue that seems to work well. I wanted to share my approach in case it could help someone else facing the same problem or looking to implement something similar. Although I am using TypeScript, I believe the same strategy could be applied in JavaScript, whether with or without ES6.

The setup now includes a directory named config within my src directory, housing subdirectories for each customer like this:

config
├── dev
├── cust1
└── cust2

Each of these customer directories contains an info.ts file that exports constants such as REST endpoint URLs:

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

In addition, there is a modules.ts file in each customer directory, exporting an array of modules to be passed into the application's bootstrapper function:

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,
];

Keeping these files separate was crucial - my initial attempt had one .ts file per config, leading to circular dependencies whenever I tried importing constants from within the modules.

To handle this, I introduced a resolve.alias based on a command line argument:

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

Now, by simply running commands like:

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

I can easily switch between different configurations for both config/info and config/modules. I still need to test this approach in practice and possibly refine the interface for the various exports, but as a starting point, I'm pleased with how it's shaping up!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular 1.5 - Component for fetching HTML content with dynamic data

Help needed with using Angular Component method. Developing a main html file with its main controller containing a JSON list of client data: clients: [{ "name": "John Jackson", "age": "21", "hair": "brown", }, { "name": "Janet Doe", ...

Setting up Webpack to compile without reliance on external modules: A step-by-step guide

I am facing an issue with a third-party library that needs to be included in my TypeScript project. The library is added to the application through a CDN path in the HTML file, and it exports a window variable that is used in the code. Unfortunately, this ...

When reference variables are utilized before being parsed, what happens?

I'm a beginner learning Angular and have a question regarding the use of reference variables. Here is an example code snippet: <div class="bg-info text-white p-2"> Selected Product: {{product.value || '(None)'}} </div> <di ...

Obtaining connection data in jsPlumb can be accomplished through a variety of

I have created a compact table of nodes that allow me to drag and drop connections or manually input node IDs to establish connections between them. Despite searching through the documentation and scouring the internet for examples, I am struggling to fin ...

Strip away the HTML tags and remove any text formatting

How can I effectively remove HTML tags and replace newlines with spaces within text? The current pattern I am using is not ideal as it adds extra space between words. Any suggestions on how to improve this pattern? replace(/(&nbsp;|<([^>]+)> ...

What sets these async method declarations apart?

What goes on behind the scenes? const facade = { // A: doSomething: async () => await delegatedFunction(), // B: doSomething: async () => delegatedFunction(), // C: doSomething: () => delegatedFunction(), // D: do ...

In JavaScript, how can we determine the structure of an object similar to the str function in R language?

One of the great features in R is the use of the str function, which allows you to examine the structure of an object. For example, you can use it to analyze the structure of a parsed json object like this (I'm using json as an illustration): txt = ...

The XML response from Ajax is returning as empty

My goal is to retrieve XML data from an ajax request and extract information using the DOM. The ajax request itself seems to be working fine as I can access AjaxRequest.responseText without any issues. However, I am encountering an error message stating: ...

AngularJS: utilizing a continuous loop of Ajax requests to fetch data and updating the scope once the requests

Within my controller, I have a process where I call a factory to retrieve data from an API. Once the data is successfully fetched, it is then passed to another function for further processing. In this function, each piece of data is looped through and trig ...

Creating a visual representation of data using Google Charts to display a stacked bar chart

I wrote a script to display a stacked Google chart using JSON data stored on the wwwroot directory - <html> <head> <title>DevOps Monitoring Application</title> <link rel="icon" type="image/png" hr ...

Facing challenges with using express.static() to display an image from a directory within my server on the front end

My application showcases various items on a specific page. Each item includes an image, number, and name. The images are stored in a folder named "uploads" on the backend. I can view the images within this folder, and from the Node backend, I'm provid ...

Guidelines for creating an auto-scrolling React Native FlatList similar to a Marquee

I currently have a FlatList component set up in my project. <FlatList horizontal data={data} key={(item, index) => index.toString()} ListHeaderComponent={listHeader} renderItem={ // renderin ...

What is the best method for displaying plain text using the br tag?

My component looks like this: class News extends Component { state = { isSimple: this.props.isSimple } render() { return ( <div> <div className="extended">extended</div> simple text </div&g ...

npm encountered an error due to an invalid query string passed to parseQuery. The proper format should include a question mark at the beginning

When I executed npm run build in my vue2 project, an error message appeared stating that loaderUtils.getOptions is not a function. After running cnpm install vue-loader vue-template-compiler loader-utils, I encountered the following error: ERROR in ...

Use Enums instead of conditions in Typescript

Consider the code snippet below, which is a function that generates a CSS class based on the value of toCheck: const computeSomething = (toCheck: string) => { return clsx('flex', { 'flex-start': toCheck === 'FIRST', ...

Error: Unexpected top-level property "import/order" in ESLINT configuration

I'm in the process of setting up a guideline to include one blank line between internal and external imports. .eslintrc.json: { "parser": "@typescript-eslint/parser", "env": { "es6": true, " ...

Is it possible to use jQuery for drag-and-drop functionality?

Currently, I am working on developing a drag-and-drop widget that consists of 3 questions and corresponding answers. The user should only be able to fill in 2 answers in any order, while the third drop area should be disabled. This third drop area can be l ...

Using the "$parent" variable within multi-level directives

Currently, I am delving into a functional code. This particular code is designed to generate a basic JSON data structure by incorporating name:value pairs individually through a graphical user interface (GUI). Through a custom directive and its link functi ...

Using HTML and JavaScript to choose relatives from the extended family: Uncles and Aunts

Looking for a better way to target elements in your HTML code? <div class="chunk" id=""> <div class="chunkContent"> <div class="textLeft" ></div> <div class="textRight" ></div> <div class= ...

Obtain the response body in Nest JS middleware

Currently, I am working on developing logging middleware for my project. My main goal is to log the response body specifically in 500 responses. However, I have encountered an issue where the response body is not present in the Response object when using a ...