Reputation: 198
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:
WebpackChunkName
correctly?Upvotes: 14
Views: 9691
Reputation: 2263
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/'
},
});
Upvotes: 0
Reputation: 2549
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.
Upvotes: 5
Reputation: 2366
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 :)
Upvotes: 6