Looking for the most effective method of defining multiple configurations in a multi-build Vue js application?

I am currently developing a Vue 3 web application that is intended to be deployed for various customers, each with their own unique title, logo, and icon.
My goal is to customize the app for each customer by displaying their specific information in the TheFooter.vue component.
An essential requirement is ensuring that when the app is built for a particular customer, no other customers' data should be present in the final built files within the /dist folder after running npm run build, due to privacy concerns.

Here are some approaches I have attempted:

  1. Creating a file named customers.js to export an object structured as follows:
const customers = {
  CUSTOMER_A: {
    title: 'Customer A',
    logo: 'assets/customer_a_logo.png',
    // additional sensitive data
  },
  CUSTOMER_B: {
    title: 'Customer B',
    logo: 'assets/customer_b_logo.png',
    // additional sensitive data
  }
export default const customer[process.env.VUE_APP_CURRENT_CUSTOMER]

Then, defining a key VUE_APP_CURRENT_CUSTOMER in the .env file with values such as CUSTOMER_A, CUSTOMER_B,...
And importing customer data into TheFooter.vue as follows:

const customer = require('./customers.js').default

However, upon inspection of the final built JavaScript files in the /dist directory, it was observed that other customers' information remained accessible.

  1. Utilizing Vue CLI modes, creating individual .env.customer_x files for each customer containing specific data, then referencing the current customer during the build process using the --mode flag (e.g.

    vue-cli-service build --mode customer_x
    ). However, managing numerous .env.customer_... files may become impractical. (Are there any potential drawbacks to this approach?)

  2. Using a json file (e.g. customers.json) and attempting to import it in TheFooter.vue like so:

    import { process.env.VUE_APP_CURRENT_CUSTOMER } from './customers.json'

    It appears impossible to include variables in the import statement, necessitating the use of environment variables (for CI/CD pipelines)

Do you have any suggestions or best practices for addressing this challenge?

Thank you in advance!

Answer №1

To create multiple builds, you can follow a two-step process.

Step 1: Custom script build

Start by writing a custom build script that will trigger Webpack programmatically. Here's an example:

// build.js file
const webpack = require('webpack');

// Your webpack.config.js should export a function instead of config.
const webpackConfig = require('./webpack.config.js');

// You can get data from a separate 'customers.js' file.
const customers = [
  { title: 'App 1' },
  { title: 'App2' }
];

customers.forEach((customer) => {

  // Get webpack configuration for this customer.
  const config = webpackConfig(customer);

  // Invoke the webpack
  webpack(config, (err) => {
    /** Handle error here */
  });

});

Your Webpack config should be wrapped in a callback function like this:

// webpack.config.js
module.exports = (customer) => {

  // This function will be called from the build.js file.
  
  return {
    entry: 'index.js',
    output: { 
      // ...
    }
    // ...other webpack configuration
  };
};

Step 2: Data injection

Inject data into your JavaScript code using Webpack's DefinePlugin or similar methods. For HTML pages, utilize webpack-html-plugin with templates to set metadata such as <title> for each customer's build.

new webpack.DefinePlugin({
  CUSTOMER_DATA: JSON.stringify(customer)
});

Optimize your build script to handle async operations and ensure correct output directory settings for each customer. Additionally, consider utilizing Webpack's array configuration feature for creating multiple builds in a more modular approach.

Remember not to import the 'customers.js' file directly into your code. It should only be used during build time scripts.

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

JavaScript Mouseover Custom Trigger with d3.js Library

Currently, I am experimenting with d3.js and am interested in creating a custom event with a unique trigger. From my understanding, the 'mouseover' event occurs when the mouse pointer hovers over a specific element both horizontally and vertical ...

Obtain the text content of a WebElement using the Selenium Driver in JavaScript

Is there a way to verify if the element I've selected by its id has the expected text content? var driver = require('selenium-webdriver'); var By = driver.By; var elem = this.driver.findElement(By.id('my_id')); assert.equal(elem. ...

Align the center of the active Tab in Material UI

Is it feasible to position the active tab in the center of the screen horizontally, excluding cases where the first or last tab is selected? <Tabs className={classes.tabs} indicatorColor='primary' scrollB ...

Eslint is not functioning properly on the local machine

Having trouble setting up eslint for my project. When I try to run eslint --init, I keep getting this error: /usr/lib/node_modules/eslint/lib/cli.js:18 let fs = require("fs"), ^^^ SyntaxError: Unexpected strict mode reserved word at exports.runInThis ...

Adjusting the dimensions of a div to accommodate varying text lengths

I'm currently facing an issue where I have multiple divs all sharing the same "Text" class. These divs don't have set width or height values, and are adjusting based on the content inside them, which varies in width. The problem arises when other ...

Choosing an option from the dropdown menu with the help of the incredible HTMX framework

I attempted the provided solution but unfortunately, it did not yield the desired outcome. Upon checking the HTMX log, it appears that everything is set up correctly. Can anyone point out what mistake I might be making in this scenario? document.getElem ...

Getting started with React Native project

Just dipping my toes into the world of React Native and looking for recommendations on the best starter kit/generator to kickstart my projects. Tried out "create-react-native-app" already, but curious if there are any other generators or kits out there tha ...

Utilize JavaScript/jQuery to check for upcoming deadlines in a SharePoint 2013 list

I need to check if an item is due based on its date. When a user creates an item with a date in the format MM/DD (e.g., 06/15), I want to determine if that date falls within the next 30 days, turning it red, within the next 60 days, turning it orange, or g ...

How can I stop TypeScript from causing my builds to fail in Next.js?

Encountering numerous type errors when executing yarn next build, such as: Type error: Property 'href' does not exist on type '{ name: string; }'. This issue leads to the failure of my build process. Is there a specific command I can ...

Generate and retrieve an HTML file without storing it in the filesystem using Node.js and Express

I have a node application that dynamically generates an HTML file and then allows users to download it. Is there a way to create and download a file without storing it in the filesystem first? The current implementation uses fs.writeFile(): import fs fro ...

Developing an interactive selector within the on() event handler

My goal is to utilize the on() event for managing dynamically created code. It functions properly when the selector is hardcoded in the on() event. However, I aim to enable it to select different elements depending on which box they choose. $("body").on( ...

Persistent change issue with JQuery CSS function

Looking for some help with a button-bar div that I want to display only after the user clicks on a "settings" button. Currently, I have set the button-bar div to have a display:none property in my css file. However, when the settings button is clicked, t ...

The EXIF-JS data is becoming inaccessible beyond the method's scope

Currently, I am in the process of developing a web application using Angular 8. My main objective is to access the exif data of an input image outside the getData method by assigning the obtained data to a global variable. However, when attempting to acces ...

Displaying only a section of a webpage using AJAX

Currently, I am utilizing an ajax call to showcase a PHP page, which is functioning correctly as shown below: <script type="text/javascript"> var xhr = false; if (window.ActiveXObject){ xhr = new ActiveXObject("Microsoft.XMLHTTP"); ...

Bring back object categories when pressing the previous button on Firefox

When working with a form, I start off with an input element that has the "unfilled" class. As the user fills out the form, I use dynamic code to remove this class. After the form is submitted, there is a redirect to another page. If I click the "back" ...

Freed Object3D from memory

When loading a model from an obj file along with the mtl file, what is the correct way to dispose of or deallocate all the geometry, materials, and textures in the returned Object3D in r55? ...

Challenges arise when trying to integrate Vee-Validate's <Field /> component with Vue Multiselect

Seeking assistance from the community, as I seem to be encountering some issues with integrating the Field component with the Multiselect element. Within a Metronic8 wizard that receives input fields from 5 different steps, this specific integration is pro ...

The Isomorphic-style-loader is throwing an error: "Cannot read property 'apply' of null"

Despite encountering the same error and exploring various solutions, I have yet to resolve my issue, potentially due to my limited understanding of the React structure. It seems that the error is stemming from context.insertCss.apply(context, styles) not ...

Find the total duration of all items within an array by utilizing the Moment.js library

Within an array of objects, each object contains a field named "duration" that represents a string. Here is an example of one such object: { id: 14070 project: {id: 87, name: "Test project for time tracking"} issue: {id: 10940} user: {id ...

What is the best way to maintain user authentication using Firebase?

After trying a few solutions I found, I am still struggling to persist user authentication with Firebase after a page refresh. It seems like I might be missing some key concepts. I have been following the Firebase documentation and attempted to implement ...