Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can we pass parameters to an already built Vue JS app?

We have a Vue app that connects to a Web Service and get's some data. The web service URL is different, depending on the location we install the app on.

I first thought of using .env files, but later I realized these files get injected into the minified .js files.

Having this in my main.js was very convenient in the case of .env files:

Vue.prototype.ApiBaseUrl = process.env.VUE_APP_APIBASEURL
Vue.prototype.PrintDocsFolder = process.env.VUE_APP_PRINTDOCSFOLDER
Vue.prototype.TicketPrintWSocket = process.env.VUE_APP_TICKETPRINTWSOCKET   

The app is already built. I don't want to build the app for each of the hundred locations we have to deploy to. I'm not sure about the "official" approach for this.

Is there any out of the box solution in Vue that can allow this configuration? Basically we need to have a file in the root folder of the built app, and read values for our Vue.prototype.VARIABLES.

We are using vue-cli 3.

like image 808
Jack Casas Avatar asked Sep 11 '20 14:09

Jack Casas


1 Answers

Like others have said, you can do this at runtime via a network request. If you don't know where you're deploying to until you're live, you'll need to do something like this.

Alternatively, you can do this at an infrastructure and networking level. Sometimes for A/B testing systems, that's how it's done.

Alternatively, you can do this at build time. I've done both... for static assets like images, sometimes you cannot do this at runtime and you need to replace the public urls at build time. For the network request approach, fetching a static json file with the mappings you host is a definite possibility.

You were very close with the idea of using .env files.

Build-time approach with Vue CLI

In Vue CLI, you get to use the Webpack's DefinePlugin for free by specifying variables in your .env files prefixed as such: VUE_APP_THE_API_URL and then using it like process.env.VUE_APP_THE_API_URL. Docs.

Usage

In your source, use process.env.VUE_APP_THE_API_URL and .env files. Reference your API url in your source code as process.env.VUE_APP_THE_API_URL and then you should use the .env files, like you were planning to, to switch between the dev-only value and a production-only value.

The production-only value is gonna be fake and very unique so that when you find + replace it, it will be distinct.

Find + Replace the fake API_URL you built with

After you're done building your application for production, you're going to loop over a mapping file (json, js, whatever) which contains the API urls you're going to deploy to.

You'll use the filesystem and find + replace to replicate your app as many times as you need before doing a deploy via S3, fastly, etc. You can do this in a bash script or using node + execa or node + fs.

Why you might need to do this

I had to do this at build time because modifying certain assets is not possible at runtime due to optimizations done by webpack loaders where they hard-code things like the public path so it is faster. With hundreds of API/CDN urls, it would be extremely inefficient to rebuild the application over and over.

How Vue CLI does it (if you don't wanna do VUE_APP_*)

Vue CLI is ontop of webpack and this is kind of an advanced use case, so you'll want to set configureWebpack inside of vue.config.js and point that to a require('webpack.config.js') file. You want to do this in Webpack or just within your build process (bash, node, gulp, whatever).

Vue CLI 3 is tied to the major webpack version. Right now that's Webpack 4. I'm going to give you the Webpack 4 answer for your problem, but I think they're changing the plugin name in Webpack v5.

Define Plugin

The plugin you want is the DefinePlugin. Just do the above steps, but you'd be manually setting { plugins: [ new DefinePlugin() ] } with the options you want. You'd do this if you didn't wanna do VUE_APP_* as the prefix to your env variables.

like image 54
Jess Avatar answered Sep 26 '22 00:09

Jess