Skip to content

Commit 75ec093

Browse files
committed
Always outputting runtime.js
This is a subjective decision we made, because we thought it would cause less "confusing" moments (i.e. when 2 different entries would not share the same modules). Unfortunately, the single runtime chunk causes a strange bug with mini-css-extract plugin where, under some conditions, the output CSS uses the chunk filename instead of "filename".
1 parent f9a0799 commit 75ec093

File tree

7 files changed

+134
-40
lines changed

7 files changed

+134
-40
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
* [BC BREAK] Webpack was upgraded to version 4. This includes a number of major
66
and minor changes. The changes are listed below.
77

8+
* [BC BREAK] A new `runtime.js` file is now *always* output and must be
9+
included in your layout (before all other script tags for files output
10+
by Encore). You can disable this by calling `Encore.disableSingleRuntimeChunk()`.
11+
But note: if you include multiple entries on the same page, when the
12+
runtime is disabled, each entry will *not* share modules (e.g. if they
13+
both require `jquery`, they will receive 2 separate objects).
14+
815
* [BC BREAK] If you're using `createSharedEntry()`, the name of the
916
`manifest.js` file is now `runtime.js`. You will need to update
1017
your `<script>` tag to point to the new `runtime.js`.

index.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,34 @@ class Encore {
404404
return this;
405405
}
406406

407+
/**
408+
* Tell Webpack to *not* output a separate runtime.js file.
409+
*
410+
* The runtime.js file is useful when you plan to include
411+
* multiple entry files on the same page (e.g. a layout.js entry
412+
* and a page-specific entry). If you are *not* including
413+
* multiple entries on the same page, you can safely disable
414+
* this and remove the extra script tags.
415+
*
416+
* If you *do* include multiple entry files on the same page,
417+
* disabling the runtime.js file has two important consequences:
418+
* A) Each entry file will contain the Webpack runtime, which
419+
* means each contains some code that is duplicated in the other.
420+
* B) If two entry files require the same module (e.g. jquery),
421+
* they will receive *different* objects - not the *same* object.
422+
* This can cause some confusion if you expect a "layout.js" entry
423+
* to be able to "initialize" some jQuery plugins, because the
424+
* jQuery required by the other entry will be a different instance,
425+
* and so won't have the plugins initialized on it.
426+
*
427+
* @returns {Encore}
428+
*/
429+
disableSingleRuntimeChunk() {
430+
webpackConfig.disableSingleRuntimeChunk();
431+
432+
return this;
433+
}
434+
407435
/**
408436
* Tell Webpack to "split" your entry chunks.
409437
*

lib/WebpackConfig.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class WebpackConfig {
8787
this.stylusLoaderOptionsCallback = () => {};
8888
this.babelConfigurationCallback = () => {};
8989
this.cssLoaderConfigurationCallback = () => {};
90+
this.shouldUseSingleRuntimeChunk = true;
9091
this.shouldSplitEntryChunks = false;
9192
this.splitChunksConfigurationCallback = () => {};
9293
this.vueLoaderOptionsCallback = () => {};
@@ -320,6 +321,10 @@ class WebpackConfig {
320321
this.cssLoaderConfigurationCallback = callback;
321322
}
322323

324+
disableSingleRuntimeChunk() {
325+
this.shouldUseSingleRuntimeChunk = false;
326+
}
327+
323328
splitEntryChunks() {
324329
this.shouldSplitEntryChunks = true;
325330
}

lib/config-generator.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,13 @@ class ConfigGenerator {
400400
};
401401

402402
splitChunks.cacheGroups = cacheGroups;
403+
}
404+
405+
if (this.webpackConfig.shouldUseSingleRuntimeChunk) {
403406
// causes a runtime.js to be emitted with the Webpack runtime
407+
// this is important as a default because it causes different entry
408+
// files to "share" modules, instead of each module getting their own
409+
// fresh version of each module.
404410
optimization.runtimeChunk = 'single';
405411
}
406412

lib/plugins/mini-css-extract.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,30 @@ const PluginPriorities = require('./plugin-priorities');
2020
module.exports = function(plugins, webpackConfig) {
2121
// Default filename can be overridden using Encore.configureFilenames({ css: '...' })
2222
let filename = webpackConfig.useVersioning ? '[name].[contenthash:8].css' : '[name].css';
23-
let chunkFilename = webpackConfig.useVersioning ? '[id].[contenthash:8].css' : '[id].css';
23+
// the chunk filename should use [id], not [name]. But, due
24+
// to weird behavior (bug?) that's exposed in a functional test
25+
// (in production mode, code is uglified), in some cases, an entry
26+
// CSS file mysteriously becomes a chunk. In other words, it
27+
// will have a filename like 1.css instead of entry_name.css
28+
// This is related to setting optimization.runtimeChunk = 'single';
29+
let chunkFilename = webpackConfig.useVersioning ? '[name].[contenthash:8].css' : '[name].css';
2430
if (webpackConfig.configuredFilenames.css) {
2531
filename = webpackConfig.configuredFilenames.css;
32+
33+
// see above: originally we did NOT set this, because this was
34+
// only for split chunks. But now, sometimes the "entry" CSS chunk
35+
// will use chunkFilename. So, we need to always respect the
36+
// user's wishes
37+
chunkFilename = webpackConfig.configuredFilenames.css;
2638
}
2739

28-
const extractTextPluginOptions = {
40+
const miniCssPluginOptions = {
2941
filename: filename,
30-
chunkFilename
42+
chunkFilename: chunkFilename
3143
};
3244

3345
plugins.push({
34-
plugin: new MiniCssExtractPlugin(extractTextPluginOptions),
46+
plugin: new MiniCssExtractPlugin(miniCssPluginOptions),
3547
priority: PluginPriorities.MiniCssExtractPlugin
3648
});
3749
};

0 commit comments

Comments
 (0)