-
Notifications
You must be signed in to change notification settings - Fork 6
/
wait-external-webpack-plugin.js
110 lines (100 loc) · 2.71 KB
/
wait-external-webpack-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
100
101
102
103
104
105
106
107
108
109
110
'use strict';
const ConcatSource = require("webpack-sources").ConcatSource;
const ModuleFilenameHelpers = require("webpack/lib/ModuleFilenameHelpers");
class WaitExternalPlugin {
constructor(args) {
if (typeof args !== 'object') {
throw new TypeError('Argument "args" must be an object.');
}
this.test = args.hasOwnProperty('test') ? args.test : '';
}
getVarForGlobalVariableExternal(variableName, type) {
if (!Array.isArray(variableName)) {
variableName = [variableName];
}
// needed for e.g. window["some"]["thing"]
const objectLookup = variableName
.map(r => `[${JSON.stringify(r)}]`)
.join("");
return `${type}${objectLookup}`;
}
getVarForDefaultCase(request) {
if (!Array.isArray(request)) {
request = [request];
}
const variableName = request[0];
const objectLookup = request
.slice(1)
.map(r => `[${JSON.stringify(r)}]`)
.join("");
return `window.${variableName} && ${variableName}${objectLookup}`;
}
apply(compiler) {
const tester = {test: this.test};
compiler.hooks.compilation.tap('WaitExternalPlugin', (compilation) => {
compilation.hooks.optimizeChunkAssets.tapAsync('WaitExternalPlugin', (chunks, done) => {
wrapChunks(compilation, chunks);
done();
})
});
const wrapFile = (compilation, fileName, chunk) => {
const externalVars = chunk.getModules().filter(item => {
if (item.external) {
return true;
}
}).map(item => {
const {
request,
externalType,
} = item;
switch (externalType) {
case "this":
case "window":
case "self":
return this.getVarForGlobalVariableExternal(request, externalType)
case "var":
return this.getVarForDefaultCase(request);
default:
console.warn(`\n[wait-external-webpack-plugin] ignore: ${externalType} ${request}\n`);
return;
}
}).filter(item => {
return !!item;
})
if (externalVars.length === 0) return;
compilation.assets[fileName] = new ConcatSource(
`(function () {
var entryInit = function () {`,
compilation.assets[fileName],
`\n
};
if (${externalVars.join(' && ')}) {
entryInit();
} else {
var hasInit = false;
var callback = function () {
if(hasInit) return;
if (${externalVars.join(' && ')}) {
hasInit = true;
document.removeEventListener('load', callback, true);
entryInit();
}
};
document.addEventListener('load', callback, true);
}
})();`
);
}
function wrapChunks(compilation, chunks) {
chunks.forEach((chunk) => {
if (!chunk.hasRuntime()) return;
chunk.files.forEach(fileName => {
if (ModuleFilenameHelpers.matchObject(tester, fileName)) {
wrapFile(compilation, fileName, chunk);
}
});
});
}
}
}
module.exports = WaitExternalPlugin;