This repository has been archived by the owner on Jul 13, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 50
/
util.js
142 lines (116 loc) · 3.92 KB
/
util.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
'use strict';
const ParserHelpers = require('webpack/lib/ParserHelpers');
const uuid = require('uuid/v4');
const webpack = require('webpack');
const weblog = require('webpack-log');
const log = weblog({ name: 'hot', id: 'webpack-hot-client' });
function hotEntry(compiler) {
if (compiler.options.target !== 'web') {
return;
}
const { entry } = compiler.options;
const { name } = compiler;
const clientEntry = [`webpack-hot-client/client?${name || uuid()}`];
let newEntry = {};
if (typeof entry === 'object') {
for (const key of Object.keys(entry)) {
const value = entry[key];
if (Array.isArray(value)) {
newEntry[key] = clientEntry.concat(value);
}
}
} else {
newEntry = clientEntry.concat(entry);
}
if (compiler.hooks) {
compiler.hooks.entryOption.call(compiler.options.context, newEntry);
} else {
compiler.applyPluginsBailResult('entry-option', compiler.options.context, newEntry);
}
}
function hotPlugin(compiler) {
const hmrPlugin = new webpack.HotModuleReplacementPlugin();
if (compiler.hooks) {
// webpack@4
// eslint-disable-next-line no-loop-func
compiler.hooks.compilation.tap('HotModuleReplacementPlugin', (compilation, {
normalModuleFactory
}) => {
const handler = (parser) => {
parser.hooks.evaluateIdentifier.for('module.hot').tap({
name: 'HotModuleReplacementPlugin',
before: 'NodeStuffPlugin'
}, expr => ParserHelpers.evaluateToIdentifier('module.hot', !!parser.state.compilation.hotUpdateChunkTemplate)(expr));
};
normalModuleFactory.hooks.parser.for('javascript/auto').tap('HotModuleReplacementPlugin', handler);
normalModuleFactory.hooks.parser.for('javascript/dynamic').tap('HotModuleReplacementPlugin', handler);
});
hmrPlugin.apply(compiler);
} else {
// webpack < 4
// must come first
hmrPlugin.apply(compiler);
compiler.plugin('compilation', (compilation, data) => {
data.normalModuleFactory.plugin('parser', (parser) => {
// eslint-disable-next-line no-underscore-dangle
parser._plugins['evaluate Identifier module.hot'].reverse();
});
});
}
}
module.exports = {
modifyCompiler(compiler, options) {
// this is how we pass the options at runtime to the client script
const definePlugin = new webpack.DefinePlugin({
__hotClientOptions__: JSON.stringify(options)
});
for (const comp of [].concat(compiler.compilers || compiler)) {
hotEntry(comp);
log.debug('Applying DefinePlugin:__hotClientOptions__');
definePlugin.apply(comp);
hotPlugin(comp);
}
},
payload(type, data) {
return JSON.stringify({ type, data });
},
sendStats(broadcast, stats) {
const send = (type, data) => {
broadcast(module.exports.payload(type, data));
};
if (!stats) {
log.error('sendStats: stats is undefined');
}
if (stats.errors && stats.errors.length > 0) {
send('errors', stats.errors);
return;
}
if (stats.assets && stats.assets.every(asset => !asset.emitted)) {
send('no-change');
return;
}
send('hash', stats.hash);
if (stats.warnings.length > 0) {
send('warnings', stats.warnings);
} else {
send('ok');
}
},
validateEntry(compiler) {
for (const comp of [].concat(compiler.compilers || compiler)) {
const { entry } = comp.options;
const type = typeof entry;
if (!Array.isArray(entry) && type !== 'object') {
throw new TypeError('webpack-hot-client: The value of `entry` must be an Array or Object. Please check your webpack config.');
}
if (type === 'object') {
for (const key of Object.keys(entry)) {
const value = entry[key];
if (!Array.isArray(value)) {
throw new TypeError('webpack-hot-client: `entry` Object values must be an Array. Please check your webpack config.');
}
}
}
}
}
};