Home > Enterprise >  What is the best way to define multiple configs in a multi-build Vue js app?
What is the best way to define multiple configs in a multi-build Vue js app?

Time:10-20

I am working on a Vue 3 web application that would be built and deployed for multiple customers. Each customer has its own title, logo, icon, etc.
What I need is to build the app for every customer with its specific information (let's say showing customer info in TheFooter.vue component).
The important requirement is that when the app is going to be built for a customer, other customers' information MUST not be included in the final built files (I mean /dist folder after running npm run build) for privacy reasons.

The ways I tried:

  1. create a customers.js file and export an object like this:
const customers = {
  CUSTOMER_A: {
    title: 'Customer A',
    logo: 'assets/customer_a_logo.png',
    // other privacy related data
  },
  CUSTOMER_B: {
    title: 'Customer B',
    logo: 'assets/customer_b_logo.png',
    // other privacy related data
  }
export default const customer[process.env.VUE_APP_CURRENT_CUSTOMER]

then in the .env file, create a VUE_APP_CURRENT_CUSTOMER key with a value like CUSTOMER_A, CUSTOMER_B,...
And in TheFooter.vue import customer data like this:
const customer = require('./customers.js').default
but this way I analyzed final built js in /dist folder and other cusotmers' information were available.

  1. Based on Vue CLI modes, for every customer create a .env.customer_x file and add customer-specific data in it, then when building app refers to the current customer with --mode flag (e.g. vue-cli-service build --mode customer_x). If customers are too many, we would end up with too many .env.customer_... files. (Any other caveats for this solution?)

  2. Create a json file (e.g. customers.json) and use it in TheFooter.vue like this:
    import { process.env.VUE_APP_CURRENT_CUSTOMER } from './customers.json'
    But it seems it is not possible to use variable inside import statement, and I need to use env variables (for ci/cd pipeline)

Is there any idea or best practices for this issue?

thanks in advance!

CodePudding user response:

It is basically a two step process to generate multiple builds.

Step 1: Custom script build

Write a custom build script that will programmatically invoke Webpack. Something like this:

// 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 require this data from other `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 would be wrapped in a callback function:

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

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

Step 2: Data injection

Use Webpack DefinePlugin or some other means to inject this data into your actual JavaScript code. For the HTML pages, you can use webpack-html-plugin that can also supports this feature using templates. You will need this to set <title> and other HTML metadata for your customer's build.

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

Further, this build script should be optimized to deal with async and also ensure that output directory is adjusted appropriately for each customer.

As an additional enhancement, Webpack also supports array configuration (multiple configurations) for creating multiple builds. You can use that as it provides parallel builds out-of-box and without needing separate build.js file. I personally like to keep things separate/modular and thus explained that way.

The key to understand here is that in your actual code, you should nowhere import this customers.js file. It is a build time thing and should be imported in build time scripts only.

  • Related