13

I'm wondering if it is possible to let to a Vue App to read an external configuration file. I imagine something in which I deploy the application, ship the application with the config file; at this point it should be possibile to change the configuration in the external file without having to rebuilt the entire application. Is there someway I can achieve that result? Now I am using a separated Vuex store but i cannot change configuration without rebuilding the entire app.

I forgot to mention that the project is made with Vue CLI.

Maurizio Ricci
  • 462
  • 1
  • 4
  • 11

3 Answers3

32

You can fetch config.json from public folder and then load your Vue app in the resolve callback

Place your configuration keys in /public/config.json file

{
  "KEY": "value"
}

Then in your /src/main.js file

fetch(process.env.BASE_URL + "config.json")
  .then((response) => response.json())
  .then((config) => {
       Vue.prototype.$config = config
       new Vue({
         router,
         store,
         render: (h) => h(App)
       }).$mount("#app")
  })

You will have your configuration loaded application-wide. You can then just use

mounted() {
  this.$config.KEY // "value"
}

in your Vue components

Update Nov 23, 2022 (Adding Vue 3 Version):

// VUE 3 Version
const app = createApp(App)

fetch(process.env.BASE_URL + "config.json")
  .then((response) => response.json())
  .then((config) => {
    // either use window.config
    window.config = config
    // or use [Vue Global Config][1]
    app.config.globalProperties.config = config
    // FINALLY, mount the app
    app.mount("#app")
  })
Hammad
  • 1,268
  • 15
  • 27
  • Is it possibile to require the config file from webpack with require()? I tried with require(process.env.BASE_URL + 'config.json') but it's not working. – Maurizio Ricci Feb 07 '20 at 17:56
  • 1
    @MaurizioRicci it is not possible to use require as webpack will convert the dynamic links to inline json, which is not desired results. Key is to use `fetch()` here and fetch external json file – Hammad Feb 10 '20 at 09:57
  • 2
    Make sure you request a new file with each request by appending a dynamic parameter to the url (eg: `?t=currentTimestamp`). Otherwise browsers will cache the request. Or add the appropriate Cache-Control header – Andy Feb 11 '20 at 08:48
  • How can I access this file in a js file inside my src/ folder (e.g api.js that needs token key for requests) – AlfredoDaAs May 11 '20 at 17:34
  • What's the benefit of using `fetch` vs just adding a ` – bernie Jan 02 '21 at 12:37
  • @bernie by doing the following, you can achieve 1) loading the values dynamically & 2) waiting for the config file to be resolved before starting the Vue application – Hammad Aug 30 '21 at 13:50
  • @Hammad Can we do that in Vue 3 which uses createApp for creating new instance? – abbas Nov 13 '22 at 10:52
  • 1
    @abbas Yes, definitely you just have to wrap the `app.mount()` in the then callback of fetch – Hammad Nov 23 '22 at 08:01
  • @Hammad yes I had figured it out exactly like yours, with the only difference fetch("/config.json") – abbas Nov 24 '22 at 09:56
3

Here's how I did it:

Create a config.js file in your public folder with the settings you want:

window.VUE_APP_API_KEY = 'blahblahblah';

Then in your public/index.html add the following lines to your head section:

  <script type="text/javascript">
    var cachebuster = Math.round(new Date().getTime() / 1000);
    document.write('<scr' + 'ipt type="text/javascript" src="<%= BASE_URL %>config.js?cb=' + cachebuster + '"></scr' + 'ipt>');
  </script>

Then in your VUE app, you just have to call window.VUE_APP_API_KEY. Simple, quick :)

rip747
  • 9,375
  • 8
  • 36
  • 47
  • Why do you split the `script` tag in 2 parts and then join them with a concatenation? – bernie Jan 02 '21 at 12:34
  • 1
    @bernie cause otherwise it cause errors. See this SO question for a full explanation and various methods to escape. https://stackoverflow.com/questions/236073/why-split-the-script-tag-when-writing-it-with-document-write – rip747 Jan 04 '21 at 14:26
  • Wth vite I am getting "[vite] Internal server error: URI malformed". – IngoB Oct 29 '22 at 16:24
1

I have a route served by node which returns a dynamically created JS files and defines a global object where I store that config. Nothing that is Vue dependent.

In index.html:

 <script type="text/javascript" src="config.js"></script>

In node (server side):

  app.get('/config.js', (request, reply) => {
    reply.header('Content-Type', 'application/javascript');
    reply.send(`MyConfig = ${JSON.stringify(config)}`);
  });

In components (or anywhere else):

{
  data: () => ({
    someField: MyConfig.someField
  })
}
Andy
  • 6,869
  • 2
  • 31
  • 24
  • This solution needs an external server i.e. `node.js`. See my solution below which doesn't require any external server. Also, the suggested framework and code example doesn't correspond to any specific library – Hammad Feb 10 '20 at 11:49
  • Yes it does. I was already using Node to serve the static files (and other things) so it fit in my case. – Andy Feb 11 '20 at 08:49