Vuejs/Browser Caching Production Builds

VueJS/browser caching production builds

This problem is annoying, no doubt. Had to solve it using a custom Front end version endpoint sent in the header. I am using a rails backend and Vue + Axios as front-end. Note I don't need a service worker and hence not using one.

Essentially I am just reloading whenever there is a get request and that the version of the application has changed (the server can inform the same)

axiosConfig.js

axios.interceptors.response.use(
(resp) => {
const fe_version = resp.headers['fe-version'] || 'default'
if(fe_version !== localStorage.getItem('fe-version') && resp.config.method == 'get'){
localStorage.setItem('fe-version', fe_version)
window.location.reload() // For new version, simply reload on any get
}
return Promise.resolve(resp)
},
)

Rails Backend

application_controller.rb

after_action :set_version_header

def set_version_header
response.set_header('fe-version', Setting.key_values['fe-version'] || 'default')
end

application.rb (CORS config assuming Vue running on port 8080)

config.middleware.insert_before 0, Rack::Cors do
allow do
origins ['localhost:8080', '127.0.0.1:8080']
resource '*', expose: ['fe-version'], headers: :any, methods: [:get, :post, :delete, :patch], credentials: true
end
end if Rails.env.development?

Wrote a detailed article here: https://blog.francium.tech/vue-js-cache-not-getting-cleared-in-production-on-deploy-656fcc5a85fe

Browser cache issues

The following is the default configuration of the project generated by vue-cli

webpack.prod.conf.js:

output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},

You can see that the file name after npm run build has a hash value added like js/vendor.658937d99bd7b1009d76.js, so there should be no cache problem.

Then it may be that the compiled index.html file is cached on the server side, which requires modifying the server configuration to not cache the index.html file.

For example, nginx configuration:

location / {
root html;
add_header Cache-Control no-store;
index index.html index.htm;
}

This way the browser will not cache the index.html file when loading.

Vue WebApp - Load latest build

You are facing the cache problem and there is multiple ways to handle this.

Cache Control

You can control the cache with the header with max-age or no-store, no-cache to simple disable it, like this question/answer: How do we control web page caching, across all browsers?

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
https://csswizardry.com/2019/03/cache-control-for-civilians/

Cache busting

Aappending a version (example: 1.0.0) to query string of the script tag:

<script src="path/to/your/app.min.js?v=1.0.0"

and change that version for every build.

Hashing the script file

You can also use some webpack/rollup config to build the script with a hash, like app.bf43112.js

webpack

const config = {
output: {
path: PATHS.build,
filename: "[name].[contenthash].js",
},
};

Rollup

const isProduction = process.env.NODE_ENV === 'production';

export default {
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: isProduction ? 'bundle[hash].js' : 'public/build/bundle.js',
}
};

Reference: Hashed file names using Rollup

Service Worker

Another solution, that I never tested, but sounds a good method.. is creating a service worker to control how retrieve the js file:
https://developers.google.com/web/ilt/pwa/caching-files-with-service-worker

You can do things like deleting the cache, responding the cache with a response that you manually fetch with js, etc.



Related Topics



Leave a reply



Submit