laravel-mix how to fix cache issue with manifest.js

Viewed 37

I have build an SPA app (Laravel 9 API + Vue 3, laravel-mix)

On my dev pc I am using npm run watch and when I am done changing something npm run prod and send the js (using svn) on the production server.

The problem is on the production server. When refresh the page - the page is blank - and in console I have an error

manifest.js TypeError: Cannot read properties of undefined (reading 'call') at funtion i (manifest.js?id=b27......

The solution is to go in dev tools -> network -> check (disable cache) and refresh - and the app is working.

It's a cache issue and I don't know to fix it.

The app.blade.php (the main template file) I am loading the resources:

<link href="{{ mix('/css/app.css') }}" rel="stylesheet">
<script src="{{ mix('/js/manifest.js') }}" defer></script>
<script src="{{ mix('/js/vendor.js') }}" defer></script>
<script src="{{ mix('/js/app.js') }}" defer></script>

The webpack.mix.js file:

mix.js('resources/js/app.js', 'public/js')
.extract()
.vue({ version: 3} )
.sass('resources/sass/app.scss', 'public/css')
.version();

mix.alias({
    '@main_app': path.join(__dirname, 'resources/js'),
})

For every route that I load (vue-router) - is generated a js file for each componen - ex:

path: '/dashboard',
name: 'Dashboard',
meta: {middleware: [auth]},
component: () => import(/* webpackChunkName: "Dashboard" */ '../views/Dasboard')

What have I missed ???

UPDATE

I have also tested on my dev machine. Running the app with the production build (works fine), then run npm run watch then refresh the browser (without cache clear - a normal refresh) - the page is blank

ChunkLoadError: Loading chunk login failed. (missing: http://app-url/js/login.js ..... at manifest.js at Array.reduce

Again if refresh with disable cache - works

UPDATE 2

I found a possible solution (I am testing it). When building (dev, prod) I add a unique int for each js file in mix-manifest.js

const fs = require('fs')

mix.js('resources/js/app.js', 'public/js')
.extract()
.vue({ version: 3} )
.sass('resources/sass/app.scss', 'public/css')
.version()
.then((stats) => {

  let filePath = stats.compilation.options.output.path + '/mix-manifest.json'
  let fileContent = fs.readFileSync(filePath)
  let assets = JSON.parse(fileContent)

  let new_assets = {}
  Object.keys(assets).forEach(function (item) {
    let addedTimestamp = '-' + Date.now()
    new_assets[item] = assets[item] + addedTimestamp
  })

  fs.writeFileSync(filePath, JSON.stringify(new_assets, null, 4))
})
0 Answers
Related