After over a year of development and extensive testing, Phase 2 recently launched a new software product for one of our clients. The product features a Ruby on Rails API and a web app built with Webpack , Vue , and Material Web Components. The main reason we chose this stack is efficiency. The Rails community practices convention over configuration , and provides a robust collection of battle-tested libraries. Vue and Webpack allow us to assemble modular components that can be easily reused, preventing large amounts of redundant code and greatly improving maintainability.
Once the product launched and customers began using the application, our team was afforded some time to address tech debt that had built up over the past year. One of our biggest priorities was upgrading from webpack 2 to webpack 4.
Webpack 4
is faster and it transitions from having a monolithic configuration to what they're calling #0CJS (Zero-Config JS). In the end, we went from having sixteen configuration files to a single file:
vue.config.js
.
Vue recently launched their new
Vue CLI 3.0
which goes hand in hand with webpack 4. Vue CLI 3.0 does an awesome job hiding nearly all framework specific configuration behind the curtains, and provides great
documentation
for any custom configuration. One common need is an environment variable that is available in the app code, for instance an API base URL. In our case this URL is dependent on environment and tenant, meaning we can't simply save it in a
.env
file like
recommended
.
The documentation contains the following tip:
You can have computed env vars in your
vue.config.js
file.
Computing the API base URL is easy enough. We use something similar to the following code to do so:
switch(environment) {
case 'development':
case 'test':
url = `http://${process.env.HOST_IP}:3000`
break
case 'staging':
url = `https://api.staging.${process.env.NODE_TENANT}.DOMAIN.com`
break
case 'production':
url = `https://api.${process.env.NODE_TENANT}.DOMAIN.com`
break
default:
throw 'Unknown environment'
}
After searching the documentation further, we found that
chaining
allows one to tap into webpack's configuration rules and modify them, and Vue's
inspect command
enables verification of webpack's configuration. The
inspect
command is indispensable when customizing webpack 4 configuration with Vue. It allowed us to determine the exact webpack plugin to tap into and what options to set. We ended up with the following code to incorporate the API base URL:
chainWebpack: (config) => {
config.plugin('define')
.tap(([options, ...args]) => {
const processEnv = Object.assign({}, options['process.env'])
processEnv['VUE_APP_API_BASE_URL'] = JSON.stringify(url)
return [
Object.assign({}, options, {'process.env': processEnv}),
...args
]
})
}
With this our app was able to continue clear communication with our API and we were able to shift focus from addressing tech debt to implementing Cypress end-to-end testing to guarantee that the app will always deliver a consistent and expected experience to our client and their customers.