Webpack chunk names with Laravel Mix
Asked Answered
T

3

14

I want to use Webpack chunks with Laravel Mix. At the moment this list is outputted:

                                               Asset      Size        Chunks             Chunk Names
                                     /entry-point.js  3.37 MiB  /entry-point  [emitted]  /entry-point
                                                0.js  57.9 KiB             0  [emitted]  
                                                1.js  20.7 KiB             1  [emitted]  
                                               10.js  24.2 KiB            10  [emitted]  
                                               11.js  17.8 KiB            11  [emitted]  
                                               12.js  17.3 KiB            12  [emitted]  
                                               13.js  20.3 KiB            13  [emitted]  
                                               14.js  34.3 KiB            14  [emitted]  
                                               15.js  16.3 KiB            15  [emitted]  
                                               16.js  16.3 KiB            16  [emitted]  
                                               17.js  18.8 KiB            17  [emitted]  
                                               18.js  9.34 KiB            18  [emitted]  
                                               19.js  18.2 KiB            19  [emitted]  
                                                2.js   487 KiB             2  [emitted]  
                                               20.js  18.2 KiB            20  [emitted]  
                                               21.js  17.2 KiB            21  [emitted]  
                                               22.js  13.3 KiB            22  [emitted]  
                                               23.js    54 KiB            23  [emitted]  
                                               24.js  53.8 KiB            24  [emitted]  
                                               25.js  17.9 KiB            25  [emitted]  
                                               26.js  23.6 KiB            26  [emitted]  
                                               27.js  29.4 KiB            27  [emitted]  
                                               28.js  29.4 KiB            28  [emitted]  
                                               29.js  19.5 KiB            29  [emitted]  
                                                3.js   128 KiB             3  [emitted]  
                                               30.js    17 KiB            30  [emitted]  
                                               31.js  13.1 KiB            31  [emitted]  
                                               32.js  33.4 KiB            32  [emitted]  
                                                4.js   104 KiB             4  [emitted]  
                                                5.js  70.1 KiB             5  [emitted]  
                                                6.js  82.9 KiB             6  [emitted]  
                                                7.js  89.1 KiB             7  [emitted]  
                                                8.js   959 KiB             8  [emitted]  
                                                9.js  38.1 KiB             9  [emitted]  

Route definition:

export default [{
    path: '/user',
    component: Layout2,
    children: [
        {
            path: '/',
            name: 'user',
            component: () => /* webpackChunkName: "view-[request]" */ import('@/components/user'),
        },
    ]
}]

Webpack config:

/**
 * As our first step, we'll pull in the user's webpack.mix.js
 * file. Based on what the user requests in that file,
 * a generic config object will be constructed for us.
 */
let mix = require('laravel-mix/src/index');

let ComponentFactory = require('laravel-mix/src/components/ComponentFactory');

new ComponentFactory().installAll();

require(Mix.paths.mix());

/**
 * Just in case the user needs to hook into this point
 * in the build process, we'll make an announcement.
 */

Mix.dispatch('init', Mix);

/**
 * Now that we know which build tasks are required by the
 * user, we can dynamically create a configuration object
 * for Webpack. And that's all there is to it. Simple!
 */

let WebpackConfig = require('laravel-mix/src/builder/WebpackConfig');

const config = new WebpackConfig().build();

// Inject sass-loader options
config.module.rules
.filter(rule => rule.test.test && (rule.test.test('.sass') || rule.test.test('.scss')))
.forEach(rule => {
    const sassLoader = rule.loaders.find(loader => loader.loader === 'sass-loader');

    if (sassLoader) {
        Object.assign(sassLoader.options, {
            precision: 5,
            implementation: require('node-sass')
        });
    }
});

// Fix Hot Module Replacement bug
if (Mix.isUsing('hmr')) {
    // Remove leading '/' from entry keys
    config.entry = Object.keys(config.entry)
    .reduce((entries, entry) => {
        entries[entry.replace(/^\//, '')] = config.entry[entry];
        return entries;
    }, {});

    // Remove leading '/' from ExtractTextPlugin instances
    config.plugins
    .forEach((plugin) => {
        if (plugin.constructor.name === 'ExtractTextPlugin') {
            plugin.filename = plugin.filename.replace(/^\//, '');
        }
    });
}



module.exports = config;

Now I am wondering why all the files are named 0.js etc. and not like the webpackChunkName.

Additionally, I'd like to use cache-busting on the chunks as my browser always caches them, so if I re-run Webpack, I often need to clear my cache completely.

My questions are:

  • How can I make use of the WebpackChunkName correctly?
  • How can I prevent caching of the chunks?
Triglyceride answered 14/5, 2019 at 11:10 Comment(0)
F
6

I will assume you are building an application that utilizes Vue router from your question.

1) To answer your first Question, whenever you import your component in your route definition this way component: () => import('@/components/user'). you are simply telling webpack to code split your application bundle based on your routes in vue.

This allows your routes component to be lazy loaded, thereby reducing your main bundle size see https://router.vuejs.org/guide/advanced/lazy-loading.html. Each x.js file is created from the dynamic component import in your route definition and are automatically/lazily loaded when needed. (You can open your console as navigate between different routes under the xhr tab, you will see as the files are loaded.)

2) For your second question, check this other question How Can I Make Webpack Use a Cache-Busting Suffix?

UPDATE: you could also use HtmlWebpackPlugin, it has an attribute hash (boolean) that will automatically append a unique webpack compilation hash to all included scripts and css files. However it only includes css and js. You might need to hash other resources as well.

Hope it helps :)

Fula answered 17/5, 2019 at 8:56 Comment(0)
R
5

By default, the chunked files are compiled to the root of the public folder.

Personally, I find this annoying, especially for a large project, because you can end up with hundreds of .js chunk files.

I prefer to compile them to a specific folder, which I do not need to open either way.

You can achieve this by changing the chunk path in webpack.mix.js as follows:

let mix = require('laravel-mix');

mix.js('resources/assets/js/app.js', 'public/js/main');

mix.webpackConfig({
    output: {
        filename:'js/main/[name].js',
        chunkFilename: 'js/chunks/[name].js',
    },
});

In your blade, ensure you reference the correct file as follows:

<script src="{{ mix('js/main/app.js') }}"></script>

Please note you can change the name of the folder from main or chunks to your preferred name.

Rorry answered 17/5, 2020 at 19:37 Comment(0)
W
0

When i ran into this problem, i searched and routed my chunked files to inner folders using filename and chunkFilename but at that time i got some errors on browser where path of chunked files was wrong.

I have solved it by adding publicPath key in my webpack.mix.config file and inside mix.webPackConfig, please note that public path may vary depending upon your environment, in most of the production cases it would be / and on localhost in somecase it might be yourprojectfolder/public/.

mix.webpackConfig({
    output: {
        filename:'js/main/[name].js',
        chunkFilename: 'js/chunks/[name].js',
        publicPath: '/myprojectfolder/public/'
    },
});
Wine answered 27/1, 2022 at 7:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.