Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Webpack 4 splitChunks causes reused chunks to not be executed #7230

Closed
lencioni opened this issue May 8, 2018 · 26 comments
Closed

Webpack 4 splitChunks causes reused chunks to not be executed #7230

lencioni opened this issue May 8, 2018 · 26 comments

Comments

@lencioni
Copy link
Contributor

lencioni commented May 8, 2018

Bug report

I am working in a complicated app that has a bunch of bundles on every page. Most of these are "global" bundles and appear on every page. So, I have configured webpack to prevent any modules that appear in these bundles from appearing in any other bundle via splitChunks. More context on this here: https://stackoverflow.com/questions/49163684/how-to-configure-webpack-4-to-prevent-chunks-from-list-of-entry-points-appearing

What is the current behavior?

It seems that when I configure splitChunks in this way, it causes the global bundles to not be executed.

If the current behavior is a bug, please provide the steps to reproduce.

Here's a branch on a repo that reproduces this issue: https://github.com/lencioni/webpack-splitchunks-playground/tree/splitchunks-execution-problem

In this repro case, it currently logs the following to the console:

core module
core module b
non-core module
non-core b2
non-core module b

In the debugging I've done, it seems that this splitChunks configuration causes the executeModules part of the bundle that the runtime chunk is looking for to be undefined.

What is the expected behavior?

The code in the "global" bundles should be executed, which should cause the console log to look more like this:

core module
core bundle
core module b
core bundle b
core bundle c
non-core module
non-core b2
non-core module b

Other relevant information:
webpack version: 4.8.1
Node.js version: 8.9.1
Operating System: Mac
Additional tools:

@lencioni
Copy link
Contributor Author

lencioni commented May 8, 2018

I've gotten this to behave slightly better by adding this to my chunkGroup test:

if (module.depth === 0) {
  return false;
}

but it still doesn't work as expected.

@lencioni
Copy link
Contributor Author

lencioni commented May 8, 2018

This seems to maybe be happening intentionally here:

// If the chosen name is already an entry point we remove the entry point
const entrypoint = compilation.entrypoints.get(chunkName);
if (entrypoint) {
compilation.entrypoints.delete(chunkName);
entrypoint.remove();
newChunk.entryModule = undefined;
}

However it isn't clear to me from the code or the commit message (added by 18ae73d) why this behavior exists.

If I disable this entrypoint removal, I get the build that I expect and my program runs as expected.

It seems that this logic should either be removed or perhaps there should be an option added to cacheGroups that allows a cacheGroup to also be an entrypoint.

lencioni added a commit to lencioni/webpack that referenced this issue May 8, 2018
I am working in a complicated app that has a bunch of bundles on every
page. Most of these are "global" bundles and appear on every page. So, I
have configured webpack to prevent any modules that appear in these
bundles from appearing in any other bundle via splitChunks. More context
on this here:

  https://stackoverflow.com/questions/49163684/how-to-configure-webpack-4-to-prevent-chunks-from-list-of-entry-points-appearing

Unfortunately, it seems that when I configure splitChunks in this way,
it causes the global bundles to not be executed. In the debugging I've
done, it seems that this splitChunks configuration causes the
executeModules part of the bundle that the runtime chunk is looking for
to be undefined.

I believe this happens in the SplitChunks plugin to any reused chunk
that was already an entry point. I'm not entirely sure why this was done
this way, so to address my use-case, I am adding an option to
cacheGroups that allows the entrypoint to be preserved when moving
chunks into it.

Fixes webpack#7230
@amakhrov
Copy link

amakhrov commented May 8, 2018

I came across the same issue. In my old webpack config the 'common' chunk served both as a chunk with shared modules and an entry point.
In webpack 4 it no longer works.

As a workaround I ended up having two chunks: 'common' and 'common-entry'. They are always included on all pages together - so there is no good reason for them not to be a single file.

@IanVS
Copy link

IanVS commented May 11, 2018

@amakhrov if you got it working, do you mind sharing your config? I am still struggling to convert to webpack 4 because of this issue.

@amakhrov
Copy link

@IanVS here you go:

// =========
// site/common-entry.js
import session from './common/global-session';
import initHeader './common/header';

initHeader(session);

// =========
// site/page1-entry.js
import session from './common/global-session';
// ... do some page-specific stuff here

// =========
// html site/page1
<script src="/site/common.js">
<script src="/site/common-entry.js">
<script src="/site/page1-entry.js">

// =========
// html other/other2
// no site/common here - it's not relevant in the context of "other/" area
<script src="/other/other2-entry.js">

// =========
// finally, webpack config:

entry: {
	'site/common-entry': 'root/site/common-entry.js',
	'site/page1-entry': 'root/site/page-entry1.js',
	'other/other2-entry': 'root/other/other-entry.js',
}
optimization: {
	runtimeChunk: {
		name: 'runtime',
	},
	splitChunks: {
		cacheGroups: {
			common: {
				name: 'site/common',
				test: (module, chunks) => {
					const names = chunks
						.map(c => c.name)
						.filter(Boolean);

					const usedByCommonEntry = names.some(name => name === 'site/common-entry');
					return usedByCommonEntry;
				},
				chunks: chunk => {
					const name = chunk.name;
					if (name) {
						// this setup only applies to a subset of entry points, not to everything defined in config.entry
						return name.startsWith('site/');
					}

					// TODO: no name - is it on-demand chunks? not sure. in the meantime, exclude them from this common chunks setup
					return false;
				},
				enforce: true,
				// only extract modules that are also reused by other chunks!
				minChunks: 2,
				priority: -20,
			},
		}
	}
},

@expressiveco
Copy link

I tried it all the ways around but could not get a single vendors chunk. So, i have following two extract vendors and vendors-entry as @amakhrov. Are there any solution to get a single vendor chunk?

entry: {
  "vendors-entry": path.resolve(__dirname, "src/vendors.ts"),
  main: [path.resolve(__dirname, "src/index.ts") ],
}
optimization: {
splitChunks: {
  cacheGroups: {
      vendors: {
        name: "vendors",
        chunks: "all",
        minChunks: 2,
        minSize: 0
      }
  }
},
runtimeChunk: { name: "manifest" },

@amakhrov
Copy link

@expressiveco your config looks ok to me. It should create a vendor.js chunk (in addition to the vendor-entry.js and main.js entry chunks), containing modules that are shared across the both entry chunks.

What doesn't go as expected here for you?

@expressiveco
Copy link

So I want vendors and vendors-entry chunks combined into a single chunk. As you concerned, it is not sensible to have multiple chunks when they will be included in all pages.

@amakhrov
Copy link

The workaround is to get rid of vendor-entry entry chunk, and import it from your real entry point(s):

// main.js
import 'path/to/vendor-entry'; // this will execute all vendor-specific bootstrap code

console.log('main.js entry point')
// rest of main.js logic

// webpack.config
entries: {
  main: 'path/to/main'
},
cacheGroups: {
  vendor: {
    test: // only include vendor modules: using a regexp or a function
    minChunks: 1, // extract a vendor module into the 'vendor' chunk even if it's only used in a single entry chunk (main.js)
  }
}

@expressiveco
Copy link

expressiveco commented May 21, 2018

So, how should be the test function? My vendors.ts contains imports for modules. How could i simply test for them, one by one for each module?

@amakhrov
Copy link

It depends on how you define 'vendor' modules.

See the test function in my example above. The function takes the name of the module and the array of chunks which have this module included.

If you want to extract all modules used by your vendor-entry file, you would do smth like

test: (module, chunks) => {
  const names = chunks
    .map(c => c.name)
    .filter(Boolean);

  return names.some(name => name === 'path/vendor-entry');
}

@expressiveco
Copy link

expressiveco commented May 22, 2018

@amakhrov now i have following(minChunks:2) per your recommendation, but main.js is around 3mb and vendors.js is 700kb but i want all those code in vendors.js instead of main.js.

And when minChunks:1, everything is in vendor.js but the page that loads subPageEntry bundle could not access to the output.library variable, it is undefined.

entry: {
    main: path.resolve(__dirname, "src/index.ts"),
    subPageEntry: path.resolve(__dirname, "subPageEntry.ts"),
},

splitChunks: {
    cacheGroups: {
        vendors: {
            test: (module, chunks) => {
                const names = chunks
                    .map(c => c.name)
                    .filter(Boolean);

                return names.some(name => name === 'main');
            },
            name: "vendors",
            chunks: "all",
            minChunks: 1,
            minSize: 0,
        }
    }
},
runtimeChunk: { name: "manifest" },

- index.ts
import "./vendors.ts";
import "./index.less";
import "../Scripts/Master.ts"

- vendors.ts
import "./vendor-styles.ts";
import "jquery";
import "bootstrap";

@expressiveco
Copy link

expressiveco commented May 22, 2018

I applied solution of @lencioni but it did not work, only the module.depth part worked.
So, i have following, it works fine, vendors.js is 3700 kb and vendors-entry.js is 7 kb. I could not get rid of vendors-entry.js completely.

entry: {
  "vendors-entry": path.resolve(__dirname, "src/vendors.ts"),
  main: [path.resolve(__dirname, "src/index.ts") ],
}
optimization: {
splitChunks: {
  cacheGroups: {
      vendors: {
       test: (module, chunks) => module.depth > 0;
        name: "vendors",
        chunks: "all",
        minChunks: 1,
        minSize: 0
      }
  }
},
runtimeChunk: { name: "manifest" },

So, as i checked with following, manifest.js is not included in chunk groups when test: (module, chunks) => module.depth > 0; is not applied

 plugins: ([
    {
        apply(compiler) {
            compiler.hooks.afterEmit.tap('test', (compilation, callback) => {

                for (const chunkGroup of compilation.chunkGroups) {
                    console.log(`### Chunk Group name: ${chunkGroup.name} - is initial ${chunkGroup.isInitial()}`);
                    var chunks = chunkGroup.chunks;
                    console.log("--- Chunks");
                    for (var i = 0; i < chunks.length; i++) {
                        var chunk = chunks[i];
                        console.log(`### chunk : ${chunk.name} ${chunk.chunkReason}`);
                        var entryModule = chunk.entryModule;
                        if (entryModule) {
                            console.log(`### Entry Module : ${entryModule.type} ${entryModule.request}`);
                        }
                    }
                    const files = chunkGroup.getFiles();
                    for (var i=0;i<files.length;i++) {
                        console.log(`### file : ${files[i]}`);
                    }
                }
            });
        }
    }

@amakhrov
Copy link

@expressiveco

 test: (module, chunks) => module.depth > 0;

I believe this would extract all non-top-level modules from main into vendors - even your custom code that is not a part of vendors-entry. Maybe it is what you need, though.

@expressiveco
Copy link

expressiveco commented May 25, 2018

Finally, i could get a single vendors bundle that contains all vendor code while keeping the code of top-level entries in their own bundle.
Also, my library(ProjectLib) is in its own bundle instead of vendors.

- main.ts
import "vendors.ts";
... some common code for application

- vendors.ts
import "jquery";
import "bootstrap";
import "datatables.net";

- page1.ts
import "ProjectLib/MyPlugin.ts"

- page2.ts
import "ProjectLib/MyCommon.ts"

- webpack.dev.js
const ProjectLibDir = path.resolve(__dirname, "ProjectLib");
entry: {
    main: path.resolve(__dirname, "main.ts"),
    page1: path.resolve(__dirname, "page1.ts"),
    page2: path.resolve(__dirname, "page2.ts"),
},
optimization: {
    splitChunks: {
        cacheGroups: {
            projectLib: {
                test: (module, chunks) => module.context == ProjectLibDir,
                name: "projectLib",
                chunks: "all",
                minChunks: 1,
                minSize: 0,
                priority: 20,
                enforce: true
            },
            vendors: {
                test: (module, chunks) => module.depth > 0,
                name: "vendors",
                chunks: "all",
                minChunks: 1,
                minSize: 0,
                priority: 10,
                enforce: true
            }
        }
    },
    runtimeChunk: { name: "manifest" },
},

@sergei-startsev
Copy link

You could use DllPlugin and DllReferencePlugin for code splitting and ExecutableDllPlugin to execute a bundle with shared modules.

JanJakes pushed a commit to JanJakes/webpack that referenced this issue Jan 11, 2019
I am working in a complicated app that has a bunch of bundles on every
page. Most of these are "global" bundles and appear on every page. So, I
have configured webpack to prevent any modules that appear in these
bundles from appearing in any other bundle via splitChunks. More context
on this here:

  https://stackoverflow.com/questions/49163684/how-to-configure-webpack-4-to-prevent-chunks-from-list-of-entry-points-appearing

Unfortunately, it seems that when I configure splitChunks in this way,
it causes the global bundles to not be executed. In the debugging I've
done, it seems that this splitChunks configuration causes the
executeModules part of the bundle that the runtime chunk is looking for
to be undefined.

I believe this happens in the SplitChunks plugin to any reused chunk
that was already an entry point. I'm not entirely sure why this was done
this way, so to address my use-case, I am adding an option to
cacheGroups that allows the entrypoint to be preserved when moving
chunks into it.

Fixes webpack#7230
JanJakes pushed a commit to JanJakes/webpack that referenced this issue Jan 11, 2019
I am working in a complicated app that has a bunch of bundles on every
page. Most of these are "global" bundles and appear on every page. So, I
have configured webpack to prevent any modules that appear in these
bundles from appearing in any other bundle via splitChunks. More context
on this here:

  https://stackoverflow.com/questions/49163684/how-to-configure-webpack-4-to-prevent-chunks-from-list-of-entry-points-appearing

Unfortunately, it seems that when I configure splitChunks in this way,
it causes the global bundles to not be executed. In the debugging I've
done, it seems that this splitChunks configuration causes the
executeModules part of the bundle that the runtime chunk is looking for
to be undefined.

I believe this happens in the SplitChunks plugin to any reused chunk
that was already an entry point. I'm not entirely sure why this was done
this way, so to address my use-case, I am adding an option to
cacheGroups that allows the entrypoint to be preserved when moving
chunks into it.

Fixes webpack#7230
JanJakes pushed a commit to JanJakes/webpack that referenced this issue Jan 11, 2019
I am working in a complicated app that has a bunch of bundles on every
page. Most of these are "global" bundles and appear on every page. So, I
have configured webpack to prevent any modules that appear in these
bundles from appearing in any other bundle via splitChunks. More context
on this here:

  https://stackoverflow.com/questions/49163684/how-to-configure-webpack-4-to-prevent-chunks-from-list-of-entry-points-appearing

Unfortunately, it seems that when I configure splitChunks in this way,
it causes the global bundles to not be executed. In the debugging I've
done, it seems that this splitChunks configuration causes the
executeModules part of the bundle that the runtime chunk is looking for
to be undefined.

I believe this happens in the SplitChunks plugin to any reused chunk
that was already an entry point. I'm not entirely sure why this was done
this way, so to address my use-case, I am adding an option to
cacheGroups that allows the entrypoint to be preserved when moving
chunks into it.

Fixes webpack#7230
JanJakes pushed a commit to JanJakes/webpack that referenced this issue Jan 11, 2019
I am working in a complicated app that has a bunch of bundles on every
page. Most of these are "global" bundles and appear on every page. So, I
have configured webpack to prevent any modules that appear in these
bundles from appearing in any other bundle via splitChunks. More context
on this here:

  https://stackoverflow.com/questions/49163684/how-to-configure-webpack-4-to-prevent-chunks-from-list-of-entry-points-appearing

Unfortunately, it seems that when I configure splitChunks in this way,
it causes the global bundles to not be executed. In the debugging I've
done, it seems that this splitChunks configuration causes the
executeModules part of the bundle that the runtime chunk is looking for
to be undefined.

I believe this happens in the SplitChunks plugin to any reused chunk
that was already an entry point. I'm not entirely sure why this was done
this way, so to address my use-case, I am adding an option to
cacheGroups that allows the entrypoint to be preserved when moving
chunks into it.

Fixes webpack#7230
JanJakes pushed a commit to JanJakes/webpack that referenced this issue Jan 22, 2019
I am working in a complicated app that has a bunch of bundles on every
page. Most of these are "global" bundles and appear on every page. So, I
have configured webpack to prevent any modules that appear in these
bundles from appearing in any other bundle via splitChunks. More context
on this here:

  https://stackoverflow.com/questions/49163684/how-to-configure-webpack-4-to-prevent-chunks-from-list-of-entry-points-appearing

Unfortunately, it seems that when I configure splitChunks in this way,
it causes the global bundles to not be executed. In the debugging I've
done, it seems that this splitChunks configuration causes the
executeModules part of the bundle that the runtime chunk is looking for
to be undefined.

I believe this happens in the SplitChunks plugin to any reused chunk
that was already an entry point. I'm not entirely sure why this was done
this way, so to address my use-case, I am adding an option to
cacheGroups that allows the entrypoint to be preserved when moving
chunks into it.

Fixes webpack#7230
JanJakes pushed a commit to JanJakes/webpack that referenced this issue Feb 12, 2019
I am working in a complicated app that has a bunch of bundles on every
page. Most of these are "global" bundles and appear on every page. So, I
have configured webpack to prevent any modules that appear in these
bundles from appearing in any other bundle via splitChunks. More context
on this here:

  https://stackoverflow.com/questions/49163684/how-to-configure-webpack-4-to-prevent-chunks-from-list-of-entry-points-appearing

Unfortunately, it seems that when I configure splitChunks in this way,
it causes the global bundles to not be executed. In the debugging I've
done, it seems that this splitChunks configuration causes the
executeModules part of the bundle that the runtime chunk is looking for
to be undefined.

I believe this happens in the SplitChunks plugin to any reused chunk
that was already an entry point. I'm not entirely sure why this was done
this way, so to address my use-case, I am adding an option to
cacheGroups that allows the entrypoint to be preserved when moving
chunks into it.

Fixes webpack#7230
@xuqingkuang
Copy link

I was meet the same issue, and I am looking forward to the merge request could be accepted.

JanJakes pushed a commit to JanJakes/webpack that referenced this issue Mar 4, 2019
I am working in a complicated app that has a bunch of bundles on every
page. Most of these are "global" bundles and appear on every page. So, I
have configured webpack to prevent any modules that appear in these
bundles from appearing in any other bundle via splitChunks. More context
on this here:

  https://stackoverflow.com/questions/49163684/how-to-configure-webpack-4-to-prevent-chunks-from-list-of-entry-points-appearing

Unfortunately, it seems that when I configure splitChunks in this way,
it causes the global bundles to not be executed. In the debugging I've
done, it seems that this splitChunks configuration causes the
executeModules part of the bundle that the runtime chunk is looking for
to be undefined.

I believe this happens in the SplitChunks plugin to any reused chunk
that was already an entry point. I'm not entirely sure why this was done
this way, so to address my use-case, I am adding an option to
cacheGroups that allows the entrypoint to be preserved when moving
chunks into it.

Fixes webpack#7230
@snapwich
Copy link

Running into this same issue and it's preventing us from updating https://github.com/prebid/Prebid.js from webpack v3 to v4.

We have a unique (until I saw this thread, maybe some here are doing the same) issue where we have 100+ entry points with 1 entry point being the "core" module that contains shared code across all of the other entry points. This allows us to split our code into jsonp fragments and build dynamic bundles at runtime through concatenating the resulting build files depending on which additional code we want. This pattern is the foundation for our Prebid.js code module system.

I can emulate the right build output using splitChunks in webpack 4 (verified with the webpack-bundle-analyzer) except that in the webpack 4 bundle the "core" module entry point is never executed even though the other entry points are.

I have a simple reproduction of our issue here that I made before I found this issue: https://github.com/snapwich/webpack4-chunk-bug

As @lencioni mentioned as well, I can confirm that removing this code from the splitChunks plugin seems to fix the issue:

// If the chosen name is already an entry point we remove the entry point
const entrypoint = compilation.entrypoints.get(chunkName);
// commenting this code out fixes the issue
// if (entrypoint) {
// 	compilation.entrypoints.delete(chunkName);
// 	entrypoint.remove();
// 	newChunk.entryModule = undefined;
// }

@sergei-startsev
Copy link

@snapwich DllPlugin /DllReferencePlugin provided by webpack should give you more control over code splitting. You could use them with ExecutableDllPlugin to execute particular entry points within the resulted bundle.

@sumit116
Copy link

@snapwich , I found that you are using enforce: true in splitchunks cacheGroups which is not allowing the common chunk (entry) to execute. Removing it worked for me.

@snapwich
Copy link

enforce doesn't seem to have any affect on whether the entry chunk is executed or not.

JanJakes pushed a commit to JanJakes/webpack that referenced this issue Dec 12, 2019
I am working in a complicated app that has a bunch of bundles on every
page. Most of these are "global" bundles and appear on every page. So, I
have configured webpack to prevent any modules that appear in these
bundles from appearing in any other bundle via splitChunks. More context
on this here:

  https://stackoverflow.com/questions/49163684/how-to-configure-webpack-4-to-prevent-chunks-from-list-of-entry-points-appearing

Unfortunately, it seems that when I configure splitChunks in this way,
it causes the global bundles to not be executed. In the debugging I've
done, it seems that this splitChunks configuration causes the
executeModules part of the bundle that the runtime chunk is looking for
to be undefined.

I believe this happens in the SplitChunks plugin to any reused chunk
that was already an entry point. I'm not entirely sure why this was done
this way, so to address my use-case, I am adding an option to
cacheGroups that allows the entrypoint to be preserved when moving
chunks into it.

Fixes webpack#7230
JanJakes pushed a commit to JanJakes/webpack that referenced this issue Dec 12, 2019
I am working in a complicated app that has a bunch of bundles on every
page. Most of these are "global" bundles and appear on every page. So, I
have configured webpack to prevent any modules that appear in these
bundles from appearing in any other bundle via splitChunks. More context
on this here:

  https://stackoverflow.com/questions/49163684/how-to-configure-webpack-4-to-prevent-chunks-from-list-of-entry-points-appearing

Unfortunately, it seems that when I configure splitChunks in this way,
it causes the global bundles to not be executed. In the debugging I've
done, it seems that this splitChunks configuration causes the
executeModules part of the bundle that the runtime chunk is looking for
to be undefined.

I believe this happens in the SplitChunks plugin to any reused chunk
that was already an entry point. I'm not entirely sure why this was done
this way, so to address my use-case, I am adding an option to
cacheGroups that allows the entrypoint to be preserved when moving
chunks into it.

Fixes webpack#7230
@IMalyugin
Copy link

IMalyugin commented Dec 24, 2019

Had the same issue in context of:

  • multiple entry points
  • common bundle
  • expose-loader for SiteHeader and SiteFooter

Problem: When SiteHeader and SiteFooter are added to common bundle entrypoint, they do not get exposed as a result. Even when i use them along with appropriate entryPoint.

Suggested solution: is probably to move exposed header and footer on to another entrypoint, but that requires reworking server-side (changing bundle script tags).

Accepted solution: we went with adding SiteHeader and SiteFooter to every entrypoint by a function like this:

const addEntryToEach = (extra, entries) => Object.keys(entries).reduce((result, entryName) => ({
  ...result,
  [entryName]: [
    ...entries[entryName],
    ...extra,
  ],
}), {});

Looking like this in the end:

module.exports = {
  entry: {
    vendor: [...],
    ...addEntryToEach([path.resolve(__dirname, './global-exports.js')], {
      common: [ ... ],
      myEntryPoint1 : {},
      myEntryPoint2: {},
    }),
    ...
  }
};

@Shubham819
Copy link

Hi, can Any1 help me convert common chunk to split chunks
I am using webpack 4
New webpack. Optimize. Commonschunkplugin
({
Name: pollyfills,
Chunks : pollyfills
})
New webpack. Optimize. Commonschunkplugin
({
Name: vendor,
Chunks : main,
Minchunks:module => utils. IsexternalLib(module)
})
New webpack. Optimize. Commonschunkplugin
({
Name: [pollyfills, vendor]. Reverse,
Chunks : pollyfills
})

@burzum
Copy link

burzum commented Jun 15, 2020

We have the same problem and no solution to it. 😞 If there is anything else we can provide to help tracking down the issue let me now.

Webpack version: ^4.34.0
Node.js version: 12.8.0
Operating System: Windows, Ubuntu and OSX

const waAliases = require('../config/webpack-aliases');
const waEntries = require('../config/entry-files');
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
const CompressionPlugin = require('compression-webpack-plugin');

console.log(waAliases);

module.exports = {
	watch: false,
	watchOptions: {
		ignored: /node_modules/
	},
	entry: waEntries,
	output: {
		filename: '[name].js',
		path: path.resolve(__dirname, '../../webroot/'),
	},
	resolve: {
		extensions: ['.js', '.vue'],
		alias: waAliases
	},
	module: {
		rules: [
			{
				test: /\.js$/,
				include: /(src)/,
				exclude: /(node_modules|bower_components)/,
				use: {
					loader: 'babel-loader',
					options: {
						presets: ['es2015', 'stage-0']
					}
				}
			},
			{
				test: /\.(woff|woff2|eot|ttf|svg)(\?.*$|$)/,
				loader: 'file-loader?name=[name].[ext]?[hash]',
			},
			{
				test: /\.vue$/,
				loader: 'vue-loader',
			},
			{ // sass / scss loader for webpack
				test: /\.(css)$/,
				use: [
					'vue-style-loader',
					'css-loader',
				]
			},
			{
				test: /\.(sass|scss)$/,
				use: ExtractTextPlugin.extract({
					fallback: 'style-loader',
					use: ['css-loader', 'sass-loader']
				})
			}
		]
	},
	optimization: {
		splitChunks: {
			chunks: 'all',
			minSize: 30000,
			minChunks: 1,
			maxAsyncRequests: 5,
			maxInitialRequests: 3,
			automaticNameDelimiter: '~',
			name: true,
			cacheGroups: {
				commons: {
					test: /[\\/]node_modules[\\/]/,
					name: 'js/public/wa-common',
					chunks: 'all'
				}
			}
		}
	},
	devtool: 'source-map',
	plugins: [
		new VueLoaderPlugin(),
		new webpack.ProvidePlugin({
			Vue: ['vue/dist/vue.esm.js', 'default'],
			jQuery: 'jquery',
			VueI18n: 'vue-i18n',
			$: 'jquery',
			'window.jQuery': 'jquery',
		}),
		new CompressionPlugin(),
		new ExtractTextPlugin({ // define where to save the file
			filename: 'css/[name].css',
			allChunks: true,
		})
	]
};

@IMalyugin
Copy link

IMalyugin commented Jun 15, 2020

Did you try the solution I mentioned above? It helped us overcome current webpack limitations. The whole idea is that you append common chunk to each entry point. As a result, the EXECUTION part lands in each of the entry point scripts, while your common chunk still keeps all the common code. And when used together, you get the desired effect.

At least in our case, problem was caused by the fact, that if you want to add a "common" library-chunk. And that common library has some execution layer. That layer is not included anywhere, unless this common chunk is not declared as a real entry point. (So just the fact that your entry point chunk is using the code from common one - counts out)

@vankop
Copy link
Member

vankop commented Sep 15, 2021

Should work with webpack@latest. Feel free to report new issue with reproducible repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet