Vue JS Cache not getting cleared in Production on Deploy

In a short while, I might be describing what this article is going to be about. But before that, let me tell what this article is “not” about. This is not about service workers or PWA and the caching headaches that come along with it. The problem that we faced is with more of a vanilla Vue JS front end, not able to refresh itself whenever a new deployment happens. Let me try to explain it in a more lucid way.
The Problem
Vue JS is supposed to be a single page application and there is no classical server request/response with the page loading every time. This is a huge plus with frameworks like Vue and the likes of React, Angular, Svelte etc. However, whenever a new version of the application is rolled out and that the entire Javascript file is changed and ready to be served as an update to the end-user, the browser is still not aware of this change, simply because no one explicitly requesting for it. For this simple reason, the new changes that you make and deploy, are not going to be available to your end-user who has the application already open. A simple example might be a new addition/deletion to your menu item.
This is fatal. Yes, a browser refresh will make this problem go away. However, good luck telling that to your thousands of live users that have the application currently open and running.
To address this problem, I searched in various places finding for a solution. To my surprise, there were many developers with similar problems without any concrete or out-of-the-box solution readily available. Hence, I went ahead and implemented one myself and that is what I want to share with you.
The Solution
This solution is very tailor-made to my stack which has a Vue Frontend with a Rails on the backend. However, the solution is ubiquitous in terms of the concept. Essentially, whenever the front end is deployed, I am going to assign it a unique version to it. In my case, I use my last commit hash to keep things extremely straightforward.
Once I know that my server is going to send this information in “every” request, I can rest assured that the version that I am dealing with is the latest. Armed with this knowledge and the wonderful localStorage
, I simply intercept the Axios config with these few lines of code, and voila, I am done!
axiosConfig.js
axios.interceptors.response.use(
(resp) => {
let v = resp.headers['vers'] || 'default'
if(v !== localStorage.getItem('vers') && resp.config.method == 'get'){
localStorage.setItem('vers', v)
window.location.reload() // For new version, simply reload on any get
}
return Promise.resolve(resp)
})
That's it! This ensures, that whenever a new version is found in the response head “and” that the request is a GET, simply reload the current page.
Bonus
As I said earlier, I was using a rails backend, for those caught up in similar waters, this solution should help on how I ship the version number on the request. With Rails, it's unsurprisingly straightforward.
application_controller.rb
after_action :set_version_header
def set_version_header
response.set_header('vers', Setting.key_values['vers'] || 'default')
end
application.rb
(for development assuming Vue runs on port 8080)
config.middleware.insert_before 0, Rack::Cors do
allow do
origins ['localhost:8080', '127.0.0.1:8080']
resource '*', expose: ['vers'], headers: :any, methods: [:get, :post, :delete, :patch], credentials: true
end
end if Rails.env.development?
With this simple configuration, you can ensure that your solution is both fast and also the least obtrusive.
Francium Tech is a technology company laser focused on delivering top quality software of scale at extreme speeds. Numbers and Size of the data don’t scare us. If you have any requirements or want a free health check of your systems or architecture, feel free to shoot an email to contact@francium.tech, we will get in touch with you!