Webpack configuration is a part of Vue CLI setup (can be checked with vue inspect
). This is a relevant part of it:
entry: {
foo: [
'.../src/foo.js'
],
barWidget: [
'.../src/barWidget.js'
],
},
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
},
...
And HTML output is:
<script type="text/javascript" src="/assets/js/chunk-vendors.[HASH].js"></script>
<script type="text/javascript" src="/assets/js/foo.[HASH].js"></script>
and
<script type="text/javascript" src="/assets/js/chunk-vendors.[HASH].js"></script>
<script type="text/javascript" src="/assets/js/barWidget.[HASH].js"></script>
There's no problem for foo
to have as many script tags as needed, but barWidget
is widget entry point that is supposed to be loaded at once with no initial chunk dependencies. My intention is to make barWidget
be loaded with a single line of code (hash will likely be disabled for this purpose):
<script type="text/javascript" src="/assets/js/barWidget.js"></script>
But in its current state it fails to load if chunk-vendors
is omitted.
I'd prefer to keep vendors
and common
chunks as they are because they are splitted in a reasonable way and can be reused on client side between entry points, but I need barWidget
to auto-load a chunk it depends on. A less preferable way would be to disable chunks but for barWidget
only, chunk splitting in other entry points should remain unchanged.
A way to reproduce it is basically a new Vue CLI project with 2 entry points added, or any Webpack project with similarly configured splitting.
Here is the project (listed for completeness):
package.json
{
"name": "foobar",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0"
}
}
vue.config.js
module.exports = {
pages: {
foo: {
entry: 'src/foo.js',
template: 'public/foo.html',
filename: 'foo.html'
},
barWidget: {
entry: 'src/barWidget.js',
template: 'public/barWidget.html',
filename: 'barWidget.html'
},
},
};
public/foo.html
public/barWidget.html
<!DOCTYPE html>
<html>
<body>
<div id="app"></div>
</body>
</html>
src/foo.js
import { createApp } from 'vue'
import Foo from './Foo.vue'
createApp(Foo).mount('#app')
Foo.vue
<template>
<HelloWorld msg="Foo"/>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
components: {
HelloWorld
}
}
</script>
src/barWidget.js
import { createApp } from 'vue'
import BarWidget from './BarWidget.vue'
createApp(BarWidget).mount('#app')
BarWidget.vue
<template>
<HelloWorld msg="Bar widget"/>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
components: {
HelloWorld
}
}
</script>
Can barWidget
be forced to automatically load chunk-vendors.[HASH].js
by means of Webpack, without loading it explicitly in the place where barWidget.[HASH].js
is being used?
Can barWidget
entry point be forced to not use other initial chunks (chunk-vendors
, etc) and output self-sufficient barWidget.js
bundle, without affecting the way splitting works in other entry points?
Are there other options for the described scenario?
Webpack injects some code into main. js which takes care of lazy loading async chunks and stops from loading same chunks again and again. When a route changes, React router calls a Webpack function to load a chunk file and Webpack after done loading runs it, which chunk then would internally ask React to do something.
Chunk: This webpack-specific term is used internally to manage the bundling process. Bundles are composed out of chunks, of which there are several types (e.g. entry and child).
The html-webpack-plugin is configured by setting the template property to the HTML template. Then we specify the output name with filename , and finally we associate it with one or more of the entry points with the chunks property. After saving this file, we can ask webpack to generate our bundles and HTML files.
Code splitting is one of the most compelling features of webpack. This feature allows you to split your code into various bundles which can then be loaded on demand or in parallel.
The multiple JavaScript files used are also known as chunks, and hence the name of the error. What Causes the Chunk Load Error? To recap, the Chunk Load Error occurs when the browser encounters an error in fetching some JavaScript files, which were dynamically imported. There are a couple reasons you may have encountered this error:
That is a simple concept of Chunk Loading. The most common methods of making sure that chunks outside of the Spawn Chunks are loaded, is moving an entity (usually an Item) through a Nether portal, or using hoppers on the chunk border between the spawn chunks or any other chunk that is always loaded and an unloaded chunk.
In order to keep a chunk loaded, you need to attach a self-fixing chunk loader module to it. Building a successful chunk loader will keep your farms and machines automated for as long as possible.
The only chunks that are 100% always loaded when a Player is online and in the Overworld are the 256 chunks inside a 16x16 grid of chunks centered around the worldspawnpoint. These chunks are called the Spawn Chunks. These chunks will always be loaded as long as a player is in the overworld.
I think that what you want is what is described in this webpack issue reply
the reply uses a function to exclude the dependencies of a specific entrypoint from being included in a chunk:
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
// ... your current config, just change the chunks property
// Exclude pre-main dependencies going into vendors, as doing so
// will result in webpack only loading pre-main once vendors loaded.
// But pre-main is the one loading vendors.
// Currently undocument feature: https://github.com/webpack/webpack/pull/6791
chunks: chunk => chunk.name !== "barWidget"
}
}
}
},
to do this with vue should be just a matter of changing the webpack config in the vue.config.js file like this:
module.exports = {
configureWebpack: config => {
config.optimization.splitChunks.cacheGroups.vendors.chunks =
chunk => chunk.name !== "barWidget";
}
}
I haven't tried this but I think it should work as is or with some minimal tweaks
You can use a function to filter the chunks. See this Webpack issue
vue.config.js
module.exports = {
pages: {
foo: {
entry: 'src/foo.js',
template: 'public/foo.html',
filename: 'foo.html'
},
barWidget: {
entry: 'src/barWidget.js',
template: 'public/barWidget.html',
filename: 'barWidget.html',
chunks: ['barWidget']
},
},
chainWebpack: config => {
if (process.env.NODE_ENV !== 'test') {
config.optimization.splitChunks({
cacheGroups: {
defaultVendors: {
name: `chunk-vendors`,
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: chunk => chunk.name !== "barWidget"
},
common: {
name: `chunk-common`,
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
})
}
}
}
Note the pages.barWidget.chunks
- it is needed because otherwise HtmlWebpackPlugin includes vendors chunk into barWidget.html
even it is not needed at all...
Result:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With