5

I'm creating a frontend project in VueJS 2 (and Vue-CLI 3) that will be used by different clients and I would like to be able to import basically everything I need (JS files like mixins and component code and CSS/LESS files) during the webpack build process parametrically based on the CID that would be stored in: 1) the Vue .env file or 2) somewhere in the webpack config file or 3) passed as a parameter to npm run watch and npm run build.

I've searched about many solutions (Webpack plugins etc.) but none of them are simple or elegant nor am I really able to understand the inner workings of the Webpack to implement those solutions and most are related to the dynamic loading not the dynamic build process.

Different clients require different code and styling so for example:

<template>...</template>
<script src="./component-code.js"></script>
<style src="@/styles/component-style.less"></style>

These paths would need to turn into something along these lines:

<template>...</template>
<script src="./CLIENTID/component-code.js"></script>
<style src="@/styles/CLIENTID/component-style.less"></style>

...so that the Webpack can replace these CLIENTID references when compiling with real folder names whatever those may be. This would also have to work for any other file paths (e.g. when using statements like import something from "./path/CLIENTID/to/file";).

What would be the easiest solution to injecting such a variable into the build process? Thanks!

  • Did you end up going to production with the solution proposed below? I'm facing a similar challenge, but don't have many truly client-specific components. – ebbishop Feb 04 '19 at 21:29
  • 1
    Actually no, I implemented an anti-pattern that uses CSS classes and JS conditions that temporarily works (imports all code for all the projects) because of our timeline but I plan on refactoring the project to use the solution outlined in the selected answer where Webpack would dynamically import the files based on an environment variable. It's not a large project nor a high-priority one. However, when I do get around to refactoring it I'll post more details here. – Aleksandar Bencun Feb 05 '19 at 15:49
  • Just a small update on this - I did go ahead with the accepted answer eventually and refactored the app to use the CLIENTID as an alias in the project file paths. And it worked great for us. It's not 100% perfect but it's very flexible and easy to set-up and much easier to maintain this way. Recommended way to go for this use case when it comes to achieving this goal without too much messing with the default Vue project set-up. – Aleksandar Bencun Feb 23 '20 at 21:44

1 Answers1

6

As one option, it is possible to use combination of aliases and architectural rules in order to achieve requested functionality.

1) Pass CLIENTID through an environmental variable or export it from any custom config file. Since CI is mentioned, let's suggest process.env is used.

2) Create aliases for all relevant paths that should be available for imports. It can be done in vue.config.js (in case of @vue/cli 3.0+) or inside a webpack config file.

Example for paths mentioned above:

'~styles': `src/styles/${process.env.CLIENTID}`
'~components': `src/components/${process.env.CLIENTID}`
'~something': `src/something/${process.env.CLIENTID}`

3) Change project structure to contain client specific component's into separate folders, while keeping shared code available via default paths.

4) Use aliases, that will resolve correct paths:

import CustomButton from '~components/custom-button.vue'

If you have a plan to bring many versions for different clients, it may be useful to refactor project architecture to something that will split all relevant assets for each CLIENTID, e.g.:

project |
        |-- common     |
        |              |--styles
        |              |--components
        |               
        |--CLIENTID_1  |
        |              |--styles
        |              |--components
        |
        |--CLIENTID_2  |
                       |--styles
                       |--components

This way aliases will be event more convenient to declare and use:

'~common': `src/common`
'~client': `src/${process.env.CLIENTID}`  

import CommonButton from '~common/components/common-button.vue'
import CustomButton from '~client/components/custom-button.vue'
aBiscuit
  • 4,414
  • 1
  • 17
  • 28
  • 1
    An interesting approach. I could then even split the codebase into the Git submodules. – Aleksandar Bencun Dec 06 '18 at 09:50
  • So I used [configureWebPack](https://cli.vuejs.org/config/#configurewebpack) and created aliasses under [resolve](https://webpack.js.org/configuration/resolve/). Example [here](https://stackoverflow.com/a/65702131/1641941) but it seems there are multiple ways of doing this. – HMR Jan 13 '21 at 12:50