laravel-mix: Webpack dynamic chunk loading not working because of publicPath setting

I have a single page application and use vue-router in combination with async components. Webpack therefore creates separate chunks for each page and they are loaded when the user wants to access the route.

Dynamic chunk loading is not working right now because of the output.publicPath setting. In the default Mix configuration, webpack output.publicPath is set to ./ and javascript files have the path /js/[name].js.

When webpack wants to load a new chunk, then it inserts a script tag:

script.src = __webpack_require__.p + "/js/" + chunkId + ".js";

where __webpack_require__.p = "./" because of the mentioned publicPath setting.

For chunk id 7, the resulting path is .//js/7.js and will be expanded to http://localhost:8000//js/7.js. But the php artisan serve webserver does not deliver the public/js/7.js file because of the additional / in the url. Instead, we get a 404 error.

Even worse, when we are on a vue-router route user/17/edit and webpack wants to load chunk 7, then the resulting url is http://localhost:8000/user/17/edit/js/7.js and it will obviously not work.

We cannot just change publicPath to / (without .), because then we will get //js/7.js which is in fact http://js/7.js and makes no sense either.

The cleanest solution probably is the following:

  • Webpack’s output.publicPath will be set to / in normal operation. When using HMR, then the path should be http://localhost:8080/. This can be achieved by modifying this line.
  • Script names should not start with a leading slash, i.e. the names are js/app.js, js/7.js, … This can be achieved by modifying this line to .replace(this.publicPath + '/', '').
  • The Manifest.transform function will ensure that all paths in the mix-manifest.json file will start with a slash as required by laravels mix helper function. This can be achieved by inserting if (!path.startsWith('/')) path = '/' + path; above this line.

Please let me know what you think of my proposed solution. If you agree, then I’ll create a PR.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 15 (1 by maintainers)

Most upvoted comments

@SebastianS90

I encountered a similar problem today, my somewhat dirty fix is:

.webpackConfig({ output: { filename: '[name].js', chunkFilename: 'js/[name].app.js', publicPath: '/' } });

Hope it helps you too.

I’m using this with laravel-mix 2.0.0 in order to have chunks work with HMR, dev and prod

if (mix.config.hmr) {
    mix.webpackConfig({
        output: {
            chunkFilename: '[name].js',
        }
    });
} else {
    mix.webpackConfig({
        output: {
            publicPath: '/',
            chunkFilename: '[name].[chunkhash].js',
        }
    });
}

I have the same issue with laravel-mix 1.2.1 Seems like the fix was removed?

 "laravel-mix": "^6.0.6", still same problem

I’m having the same issue too, please revert this fix

Here is the working config for Jigsaw:

const mix = require('laravel-mix');
const publicPath = 'source/assets/build'; 

require('laravel-mix-jigsaw');

mix.disableSuccessNotifications();
mix.setPublicPath(publicPath);

mix.jigsaw()
    .js('source/_assets/js/app.js', 'dist/app.js')
    .sass('source/_assets/scss/app.scss', 'dist/app.css')
    .webpackConfig({
        output: {
            publicPath: '/assets/build/',
            chunkFilename: 'dist/[name].[chunkhash].js',
        }
    })
    .version();

You can remove the stuff about dist folder.