8

The Problem

I have a problem with cached Vue.js components and I can't reproduce this problem on my devices but every client-side update we get users complains about broken interfaces and only clearing browser cache helps.

I use Laravel + Vue.js and it's multipage app.

Strategy

All components described in one file which included in app.js and it looks like this:

Vue.component('task-feed', () => import('./components/task/task-feed'/* webpackChunkName: "/js/components/task-feed" */));
Vue.component('task-item', () => import('./components/task/task-item'/* webpackChunkName: "/js/components/task-item" */));

There are vue.js async components.

And then i have configured webpack.mix like this:

let mix = require('laravel-mix');
const webpack = require('webpack');
const ChunkManifestPlugin = require('chunk-manifest-webpack-plugin');
const WebpackChunkHash = require('webpack-chunk-hash');
mix.disableNotifications();
let config = {
    watchOptions: {
        ignored: /node_modules/
    },
    resolve: {
        alias: {
            'vue$': mix.inProduction() ? 'vue/dist/vue.runtime.min.js' : 'vue/dist/vue.runtime.js',
        }
    },
    output: {
        chunkFilename: mix.inProduction() ? '[name].[chunkhash].js' : '[name].js',
    },
    plugins: [
        new webpack.HashedModuleIdsPlugin(),
        new WebpackChunkHash(),
        new ChunkManifestPlugin({
            filename: '/js/chunk-manifest.json',
            manifestVariable: 'webpackManifest',
            inlineManifest: true,
        }),
    ],
};

mix.webpackConfig(config);

I'm using ChunkManifestPlugin here, that plugin creates chunk-manifest.json and i load it in the main layout like this:

window.webpackManifest = JSON.parse(@json(file_get_contents(public_path('/js/chunk-manifest.json'))));

Questions

What could be wrong here? Can anyone suggest the way to solve this?

miken32
  • 42,008
  • 16
  • 111
  • 154
Vaulverin
  • 85
  • 1
  • 4
  • Pls describe the complaints ;) What goes wrong? – Thomas Nov 16 '18 at 13:46
  • We get users complains about broken interfaces and only clearing browser cache helps. – Vaulverin Nov 16 '18 at 13:56
  • Assuming you did use mix in your blade file? i.e. {{ mix('js/manifest.js') }} {{ mix('js/vendor.js') }} {{ mix('js/app.js') }} to prevent cache of main files. – Noogen Nov 16 '18 at 14:17
  • Since you're using laravel and mix, if you haven't, I would suggest doing `mix.extract` and use `mix` helper in blade to version cache main files (manifest,vendor,app) for browser. Then just use `WebpackChunkHash` to handle chunk file version and caching for browser. – Noogen Nov 16 '18 at 15:48
  • Yes we use mix function for any resource file and extraction vendor file too. The problem not in main files but in chunk files. – Vaulverin Nov 17 '18 at 09:11
  • As I mentioned, all you need is `WebpackChunkHash`. I think your issue is with `ChunkManifestPlugin`, you do not need it. I think that plugin has issue, no updates has been published for a year (see queued github issue not yet published). It is also describe as "allows to actually leverage long-term caching," which is not what you want here. – Noogen Nov 17 '18 at 15:57
  • @Vaulverin were you able to sort out your caching issues? We're experiencing the same issues when we deploy an update. Client has issues until they clear their cache. We're also using Laravel, Vue, Mix with `CommonsChunkPlugin`. We also set our index to not cache, but it seems like the async chunks hang on to cached versions. – James Apr 03 '19 at 23:06
  • No, I still don't know how to solve this problem. I tried to change plugin to WebpackChunkHash as mentioned in this discussion, but it didn't has any effect. – Vaulverin Apr 05 '19 at 15:15

2 Answers2

6

In webpack.mix.js change it to this:

mix.config.webpackConfig.output = {
    chunkFilename: 'scripts/[name].[chunkhash].js',
    publicPath: '/',
};

Refer to this article for more information.

jtate
  • 2,612
  • 7
  • 25
  • 35
ecgk
  • 76
  • 1
  • 3
0

Configure webpack.mix.js to version your files

let version = 0;

mix.config.webpackConfig.output = {
    chunkFilename: 'v/' + version + '/scripts/[name].js',
    publicPath: '/',
};

mix.js('resources/js/app.js', 'public/v/'+version+'/js')
    .sass('resources/sass/app.scss', 'public/v/'+version+'/css');