How to create a config.js file in the public folder

Hi. I have a Vue project that consumes a Rest API.
I need to have a javascript configuration file in the “public” folder to prevent “build” from minifying and merging with the rest of the code. I need to do that because this application is going to be used in different places for different clients and therefore I need to be able to configure it easily and quickly without having to “build” again. Environment variables don’t work for me in this case. How can I easily import that file into modules? if I use “import config from ‘…/…/public/config.js’” it won’t work for me in the development phase.
So the short question is how to create a configuration file that is not affected by the “build” phase and works for both development and production.
This application will run on a Tomcat in the root folder.
I am a newbie programmer so I would appreciate an example. Thank you very much.

3 Likes

Does it have to be a JavaScript file rather than JSON?

If it were JSON then you could load it in using an AJAX request, much the same as accessing your API.

Accessing a JavaScript file is more awkward. In theory it is possible to use import to pull in a module URL but I’m not sure whether you could use that to do what you want.

You could also add a <script> tag to the HTML to pull in the relevant file. That relies on the file exposing the config in a suitable way. Just using export isn’t going to work, it’d need to hook into globals via window in some way. Those globals would then be accessible in your other code.

2 Likes

Hi. Thanks for answering. Both a JSON and a JS can serve me, although I prefer a JS since they allow comments. Currently I have a configuration file in the path “assets / js / config.js”, but at the time of “build” it mix and compact all the code. So if I want to modify anything, I have to do “build” again. What i would like it that when I build, it leaves that configuration file unchanged so that I can modify it without having to “build” again. Do you know how I can do that?
If I use a JSON with ajax, I will have a problem. And it is that the route to import the json is not the same in production as in development. And I would not know how to solve that in Vue in a simple way.

1 Like

I don’t know what you mean when you say ‘the route to import the json is not the same in production as in development’. I don’t see why it would be different.

I don’t think there’s any way you can get this working using either import or require. Either way you’ll end up with the file being pulled into the build and merged/minified with everything else.

To keep the file separate, put it in the public folder. Then use one of the techniques I described previously to pull it in.

1 Like

I’m going to explain myself a little better. I am creating an application with Vue2. (vue-cli 4.5.9). This application is generic and it will work on different servers for different clients, so I need to have an external javascript configuration file to be able to modify it after doing “build”. In order to change ip, colors, etc … I have tried to put that config file in the “public” folder and then I import the settings at various points in my application as follows "import config from ‘@ / … / public / config .js’; ". The problem is that when using that import, what vue does is include that configuration file in the main chunk. So the result is that I have duplicate code (in the main “chunk” and in the config file of the “dist” folder), and another problem is that although I modify my configuration file that is in the “dist” folder,vue ignore the changes because the code that is in the “chunk” is taken by default.

Does anyone know how to make me catch the code of the external file and not duplicate it in the “chunk”?

I have also tried configuring a new “entry”, but the problem that Vue minifies it and adds a lot of code making it very impractical to edit it. And I have not found a way for vue to stop minifying only 1 of the “chunks”.

In the end I have achieved it in the following way.
1st put the file “config.js” in the public folder. All your configuration must be inside an IIFE function.
2nd go to main.js and import it. You can do it with a mixin, plugin, or simple code. But you must do it by HTTP request as the “import” and “require” are processed by webpack.
3rd The resulting string is parsed by “eval ()”.
4th the result of “eval ()” is stored inside a mixin property.
5th we access from any point of our application using that property.
Tip: You can export your vue instance, and then import it anywhere in your code to use the global variable.
I’m sure there are many other ways to achieve the same, but this has worked for me and I share it in case it suits someone.

Hello, I am building an application very similarly where I don’t use an .env file but use a config file instead so we don’t have to rebuild every time the config file is updated.

On step 2 in your solution, could you provide the an example of how you imported the config file via https in a mixin or plugin?

Thanks so much!

there you have my main.js. It can give you some ideas.
You should not take that entire code as it has some errors or bad practices. But the import code of the external configuration file is fine and works perfect.

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)
import { BootstrapVue } from 'bootstrap-vue'
import {
    BIcon,
    BIconChevronDoubleDown,
    BIconChevronDoubleUp,
    BIconEyeFill,
    BIconEyeSlashFill
} from 'bootstrap-vue'


Vue.use(BootstrapVue)
Vue.component('BIcon', BIcon)
Vue.component('BIconChevronDoubleDown', BIconChevronDoubleDown)
Vue.component('BIconChevronDoubleUp', BIconChevronDoubleUp)
Vue.component('BIconEyeFill', BIconEyeFill)
Vue.component('BIconEyeSlashFill', BIconEyeSlashFill)

Vue.prototype.$axios = axios
Vue.config.productionTip = false

import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'


Vue.mixin({
    data() {
        return {
            ebaConfig: null
        }
    },
    methods: {

        async loadEbaConfig() {
            let config = null;
            try {
                config = await axios.get(`./config.js`)
            } catch (error) {
                config = await axios.get(`'@/../public/config.js'`);
            }
            this.ebaConfig = eval(config.data);
        }
    },
    created() {
        this.loadEbaConfig();
    }
})

export const app = new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')

Friends, I have the same problem. I need read json or js file after build, and y don’t know how doing.

Can you paste the config.js source??

And then, how access the config.js content?

Best Rgs.

edit:
my config.js

(function () {
return {
VUE_APP_URL : ‘http://www.myurl.com
}
})();

my config.js file is in the public folder ( public \ config.js ).
this is my code:

    (function () {
      return {
        myvariable1: 5,
        myvariable2: [true, false, 54]
      }
    })();

to access your variable. you have to create a variable that store your main.js

`import { app } from "@/main";`

then you access your config like:

`app.config.myVariable1`

Be carefull using eval(). It is not only a security hole. It also has limitations. I’ve had to stop using that option because when my config file reached a certain size, it stoped reading it entirely.

Where did you do the import? I’m using the config variable in the main.js
But is failing as you suggested, but seems like the cleaner solution

This post is where I ended up looking when I wanted to use a dynamically imported JSON file from a public folder. I went about it in a slightly different way though:

  1. Convert the JSON file into a simple JS variable in a conf.js file:
    e.g.
var srcConf={'bGreatJSON':true};
  1. In index.html, did
<script src='./conf.js'>
  1. Now that the JS variable has been declared, in my Vue component I can just look for the window.srcConf and assign it if it exists in mounted or created:
if(typeof window.srcConf!='undefined')
  this.sConf=window.srcConf;

This also avoids the CORS issue I ran into trying to get Axios to GET the file.
Hope this helps someone!