-
-
Notifications
You must be signed in to change notification settings - Fork 198
/
shared-entry-concat-plugin.js
99 lines (80 loc) · 3.23 KB
/
shared-entry-concat-plugin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*
* This file is part of the Symfony Webpack Encore package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
'use strict';
const sharedEntryTmpName = require('../utils/sharedEntryTmpName');
const RawSource = require('webpack-sources/lib/RawSource');
function SharedEntryConcatPlugin(sharedEntryName) {
this.sharedEntryName = sharedEntryName;
}
function getChunkFilename(compilation, chunkName) {
const chunk = compilation.namedChunks.get(chunkName);
// any "additional" files - like .hot-update.js when using --hot
const additionalChunkAssets = compilation.additionalChunkAssets || [];
if (!chunk) {
throw new Error(`Cannot find chunk ${chunkName}`);
}
const jsFiles = chunk.files.filter(filename => {
return /\.js$/.test(filename) && !additionalChunkAssets.includes(filename);
});
if (jsFiles.length !== 1) {
throw new Error(`Invalid number of files for chunk ${chunkName} - got ${jsFiles.join(', ')}`);
}
return jsFiles[0];
}
/**
* @param {Source} asset
* @return {string}
*/
function getAssetSource(asset) {
let content = asset.source();
if (Buffer.isBuffer(content)) {
content = content.toString('utf-8');
}
return content;
}
SharedEntryConcatPlugin.prototype.apply = function(compiler) {
const emit = (compilation) => {
/*
* This is a hack. See ConfigGenerator.buildEntryConfig()
* for other details.
*
* Basically, the "_tmp_shared" entry is created automatically
* as a "fake" entry. Internally, it simply requires the same
* file that is the source file of the shared entry.
*
* In this plugin, we literally read the final, compiled _tmp_shared.js
* entry, and put its contents at the bottom of the final, compiled,
* shared commons file. Then, we delete _tmp_shared.js. This
* is because the shared entry is actually "removed" as an entry
* file in SplitChunksPlugin, which means that if it contains
* any code that should be executed, that code is not normally
* executed. This fixes that.
*/
const sharedEntryOutputFile = getChunkFilename(compilation, this.sharedEntryName);
const tmpEntryFile = getChunkFilename(compilation, sharedEntryTmpName);
const assets = compilation.assets;
const sharedEntryAsset = assets[sharedEntryOutputFile];
const tmpEntryAsset = assets[tmpEntryFile];
if (typeof sharedEntryAsset === 'undefined') {
throw new Error(`Could not find shared entry output file: ${sharedEntryOutputFile}`);
}
if (typeof assets[tmpEntryFile] === 'undefined') {
throw new Error(`Could not find temporary shared entry bootstrap file: ${tmpEntryFile}`);
}
assets[sharedEntryOutputFile] = new RawSource(
[getAssetSource(sharedEntryAsset), getAssetSource(tmpEntryAsset)].join('\n')
);
delete(assets[tmpEntryFile]);
};
compiler.hooks.emit.tap(
{ name: 'SharedEntryConcatPlugin' },
emit
);
};
module.exports = SharedEntryConcatPlugin;