webpack-dev-service 0.10.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/client/client.cjs +128 -0
- package/cjs/client/events.cjs +64 -0
- package/cjs/client/hot.cjs +111 -0
- package/cjs/client/index.cjs +15 -0
- package/cjs/client/main.cjs +59 -0
- package/cjs/client/ui/overlay.cjs +233 -0
- package/cjs/client/ui/progress.cjs +92 -0
- package/cjs/client/ui/utils.cjs +136 -0
- package/cjs/server/compose.cjs +56 -0
- package/cjs/server/dev/Service.cjs +269 -0
- package/cjs/server/dev/index.cjs +60 -0
- package/cjs/server/dev/middleware.cjs +96 -0
- package/cjs/server/dev/utils/fs.cjs +29 -0
- package/cjs/server/dev/utils/hash.cjs +46 -0
- package/cjs/server/dev/utils/http.cjs +227 -0
- package/cjs/server/dev/utils/path.cjs +46 -0
- package/cjs/server/dev/utils/paths.cjs +59 -0
- package/cjs/server/dev/utils/ready.cjs +23 -0
- package/cjs/server/dev/utils/setupHooks.cjs +106 -0
- package/cjs/server/dev/utils/setupOutputFileSystem.cjs +31 -0
- package/cjs/server/dev/utils/setupWatching.cjs +43 -0
- package/cjs/server/dev/utils/setupWriteToDisk.cjs +54 -0
- package/cjs/server/hot/Socket.cjs +185 -0
- package/cjs/server/hot/index.cjs +34 -0
- package/cjs/server/hot/utils.cjs +100 -0
- package/cjs/server/index.cjs +1 -1
- package/cjs/server/schema.cjs +127 -0
- package/cjs/server/utils.cjs +45 -0
- package/esm/client/client.js +126 -0
- package/esm/client/events.js +60 -0
- package/esm/client/hot.js +106 -0
- package/esm/client/index.js +10 -0
- package/esm/client/main.js +57 -0
- package/esm/client/ui/overlay.js +231 -0
- package/esm/client/ui/progress.js +90 -0
- package/esm/client/ui/utils.js +123 -0
- package/esm/server/compose.js +54 -0
- package/esm/server/dev/Service.js +260 -0
- package/esm/server/dev/index.js +58 -0
- package/esm/server/dev/middleware.js +94 -0
- package/esm/server/dev/utils/fs.js +27 -0
- package/esm/server/dev/utils/hash.js +44 -0
- package/esm/server/dev/utils/http.js +216 -0
- package/esm/server/dev/utils/path.js +42 -0
- package/esm/server/dev/utils/paths.js +57 -0
- package/esm/server/dev/utils/ready.js +21 -0
- package/esm/server/dev/utils/setupHooks.js +98 -0
- package/esm/server/dev/utils/setupOutputFileSystem.js +29 -0
- package/esm/server/dev/utils/setupWatching.js +41 -0
- package/esm/server/dev/utils/setupWriteToDisk.js +52 -0
- package/esm/server/hot/Socket.js +176 -0
- package/esm/server/hot/index.js +32 -0
- package/esm/server/hot/utils.js +93 -0
- package/esm/server/index.js +37 -0
- package/esm/server/schema.js +125 -0
- package/esm/server/utils.js +37 -0
- package/package.json +4 -4
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @package webpack-dev-service
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @version 0.10.1
|
|
5
|
+
* @author nuintun <nuintun@qq.com>
|
|
6
|
+
* @description A koa 2 middleware for webpack development and hot reloading.
|
|
7
|
+
* @see https://github.com/nuintun/webpack-dev-service#readme
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const hash = require('./hash.cjs');
|
|
13
|
+
const parseRange = require('range-parser');
|
|
14
|
+
|
|
15
|
+
function _interopDefault(e) {
|
|
16
|
+
return e && e.__esModule ? e : { default: e };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const parseRange__default = /*#__PURE__*/ _interopDefault(parseRange);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @module http
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* @function isETag
|
|
26
|
+
* @description Check if etag is valid.
|
|
27
|
+
* @param value The value to check.
|
|
28
|
+
*/
|
|
29
|
+
function isETag(value) {
|
|
30
|
+
return /^(?:W\/)?"[\s\S]+"$/.test(value);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @function parseTokens
|
|
34
|
+
* @description Parse HTTP tokens.
|
|
35
|
+
* @param value The tokens value string.
|
|
36
|
+
*/
|
|
37
|
+
function parseTokens(value) {
|
|
38
|
+
let end = 0;
|
|
39
|
+
let start = 0;
|
|
40
|
+
let tokens = [];
|
|
41
|
+
// Gather tokens.
|
|
42
|
+
for (let i = 0, length = value.length; i < length; i++) {
|
|
43
|
+
switch (value.charCodeAt(i)) {
|
|
44
|
+
case 0x20:
|
|
45
|
+
// ' '.
|
|
46
|
+
if (start === end) {
|
|
47
|
+
start = end = i + 1;
|
|
48
|
+
}
|
|
49
|
+
break;
|
|
50
|
+
case 0x2c:
|
|
51
|
+
// ','.
|
|
52
|
+
tokens.push(value.substring(start, end));
|
|
53
|
+
start = end = i + 1;
|
|
54
|
+
break;
|
|
55
|
+
default:
|
|
56
|
+
end = i + 1;
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Final token.
|
|
61
|
+
tokens.push(value.substring(start, end));
|
|
62
|
+
return tokens;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* @function isRangeFresh
|
|
66
|
+
* @description Check if request range fresh.
|
|
67
|
+
* @param context Koa context.
|
|
68
|
+
*/
|
|
69
|
+
function isRangeFresh(context) {
|
|
70
|
+
const { request, response } = context;
|
|
71
|
+
const ifRange = request.get('If-Range');
|
|
72
|
+
// No If-Range.
|
|
73
|
+
if (!ifRange) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
// If-Range as etag.
|
|
77
|
+
if (isETag(ifRange)) {
|
|
78
|
+
const etag = response.get('ETag');
|
|
79
|
+
return !!(etag && isETagFresh(ifRange, etag));
|
|
80
|
+
}
|
|
81
|
+
// If-Range as modified date.
|
|
82
|
+
const lastModified = response.get('Last-Modified');
|
|
83
|
+
return Date.parse(lastModified) <= Date.parse(ifRange);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* @function isETagFresh
|
|
87
|
+
* @description Check if etag is fresh.
|
|
88
|
+
* @param match The match value.
|
|
89
|
+
* @param etag The etag value.
|
|
90
|
+
*/
|
|
91
|
+
function isETagFresh(match, etag) {
|
|
92
|
+
return parseTokens(match).some(match => {
|
|
93
|
+
return match === etag || match === 'W/' + etag || 'W/' + match === etag;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* @function decodeURI
|
|
98
|
+
* @description Decode URI component.
|
|
99
|
+
* @param URI The URI to decode.
|
|
100
|
+
*/
|
|
101
|
+
function decodeURI(URI) {
|
|
102
|
+
try {
|
|
103
|
+
return decodeURIComponent(URI);
|
|
104
|
+
} catch (_a) {
|
|
105
|
+
return -1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* @function isConditionalGET
|
|
110
|
+
* @description Check if request is conditional GET.
|
|
111
|
+
* @param context Koa context.
|
|
112
|
+
*/
|
|
113
|
+
function isConditionalGET(context) {
|
|
114
|
+
const { request } = context;
|
|
115
|
+
return !!(
|
|
116
|
+
request.get('If-Match') ||
|
|
117
|
+
request.get('If-None-Match') ||
|
|
118
|
+
request.get('If-Modified-Since') ||
|
|
119
|
+
request.get('If-Unmodified-Since')
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* @function isPreconditionFailure
|
|
124
|
+
* @description Check if request precondition failure.
|
|
125
|
+
* @param context Koa context.
|
|
126
|
+
*/
|
|
127
|
+
function isPreconditionFailure({ request, response }) {
|
|
128
|
+
// If-Match.
|
|
129
|
+
const match = request.get('If-Match');
|
|
130
|
+
// Check if request match.
|
|
131
|
+
if (match) {
|
|
132
|
+
// Etag.
|
|
133
|
+
const etag = response.get('ETag');
|
|
134
|
+
return !etag || match === '*' || !isETagFresh(match, etag);
|
|
135
|
+
}
|
|
136
|
+
// If-Unmodified-Since.
|
|
137
|
+
const unmodifiedSince = Date.parse(request.get('If-Unmodified-Since'));
|
|
138
|
+
// Check if request unmodified.
|
|
139
|
+
if (!Number.isNaN(unmodifiedSince)) {
|
|
140
|
+
// Last-Modified.
|
|
141
|
+
const lastModified = Date.parse(response.get('Last-Modified'));
|
|
142
|
+
return Number.isNaN(lastModified) || lastModified > unmodifiedSince;
|
|
143
|
+
}
|
|
144
|
+
// Check precondition passed.
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* @function parseRanges
|
|
149
|
+
* @description Parse ranges.
|
|
150
|
+
* @param context Koa context.
|
|
151
|
+
* @param stats File stats.
|
|
152
|
+
*/
|
|
153
|
+
function parseRanges(context, stats) {
|
|
154
|
+
const { size } = stats;
|
|
155
|
+
// Range support.
|
|
156
|
+
if (/^bytes$/i.test(context.response.get('Accept-Ranges'))) {
|
|
157
|
+
const range = context.request.get('Range');
|
|
158
|
+
// Range fresh.
|
|
159
|
+
if (range && isRangeFresh(context)) {
|
|
160
|
+
// Parse range -1 -2 or [].
|
|
161
|
+
const parsed = parseRange__default.default(size, range, { combine: true });
|
|
162
|
+
// -1 signals an unsatisfiable range.
|
|
163
|
+
// -2 signals a malformed header string.
|
|
164
|
+
if (parsed === -1 || parsed === -2) {
|
|
165
|
+
return parsed;
|
|
166
|
+
}
|
|
167
|
+
// Ranges ok, support multiple ranges.
|
|
168
|
+
if (parsed.type === 'bytes') {
|
|
169
|
+
// Set 206 status.
|
|
170
|
+
context.status = 206;
|
|
171
|
+
const { length } = parsed;
|
|
172
|
+
// Multiple ranges.
|
|
173
|
+
if (length > 1) {
|
|
174
|
+
// Content-Length.
|
|
175
|
+
let contentLength = 0;
|
|
176
|
+
// Ranges.
|
|
177
|
+
const ranges = [];
|
|
178
|
+
// Range boundary.
|
|
179
|
+
const boundary = `<${hash.generate()}>`;
|
|
180
|
+
// Range suffix.
|
|
181
|
+
const suffix = `\r\n--${boundary}--\r\n`;
|
|
182
|
+
// Multipart Content-Type.
|
|
183
|
+
const contentType = `Content-Type: ${context.type}`;
|
|
184
|
+
// Override Content-Type.
|
|
185
|
+
context.type = `multipart/byteranges; boundary=${boundary}`;
|
|
186
|
+
// Map ranges.
|
|
187
|
+
for (let index = 0; index < length; index++) {
|
|
188
|
+
const { start, end } = parsed[index];
|
|
189
|
+
// The first prefix boundary no \r\n.
|
|
190
|
+
const head = index > 0 ? '\r\n' : '';
|
|
191
|
+
const contentRange = `Content-Range: bytes ${start}-${end}/${size}`;
|
|
192
|
+
const prefix = `${head}--${boundary}\r\n${contentType}\r\n${contentRange}\r\n\r\n`;
|
|
193
|
+
// Compute Content-Length
|
|
194
|
+
contentLength += end - start + 1 + Buffer.byteLength(prefix);
|
|
195
|
+
// Cache range.
|
|
196
|
+
ranges.push({ start, end, prefix });
|
|
197
|
+
}
|
|
198
|
+
// The last add suffix boundary.
|
|
199
|
+
ranges[length - 1].suffix = suffix;
|
|
200
|
+
// Compute Content-Length.
|
|
201
|
+
contentLength += Buffer.byteLength(suffix);
|
|
202
|
+
// Set Content-Length.
|
|
203
|
+
context.length = contentLength;
|
|
204
|
+
// Return ranges.
|
|
205
|
+
return ranges;
|
|
206
|
+
} else {
|
|
207
|
+
const [{ start, end }] = parsed;
|
|
208
|
+
// Set Content-Length.
|
|
209
|
+
context.length = end - start + 1;
|
|
210
|
+
// Set Content-Range.
|
|
211
|
+
context.set('Content-Range', `bytes ${start}-${end}/${size}`);
|
|
212
|
+
// Return ranges.
|
|
213
|
+
return parsed;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Set Content-Length.
|
|
219
|
+
context.length = size;
|
|
220
|
+
// Return ranges.
|
|
221
|
+
return [{ start: 0, end: Math.max(size - 1) }];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
exports.decodeURI = decodeURI;
|
|
225
|
+
exports.isConditionalGET = isConditionalGET;
|
|
226
|
+
exports.isPreconditionFailure = isPreconditionFailure;
|
|
227
|
+
exports.parseRanges = parseRanges;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @package webpack-dev-service
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @version 0.10.1
|
|
5
|
+
* @author nuintun <nuintun@qq.com>
|
|
6
|
+
* @description A koa 2 middleware for webpack development and hot reloading.
|
|
7
|
+
* @see https://github.com/nuintun/webpack-dev-service#readme
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @module path
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* @function unixify
|
|
19
|
+
* @description Convert path to unix style.
|
|
20
|
+
* @param path The path to convert.
|
|
21
|
+
*/
|
|
22
|
+
function unixify(path) {
|
|
23
|
+
return path.replace(/\\/g, '/');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* @function hasTrailingSlash
|
|
27
|
+
* @description Check if path has trailing slash.
|
|
28
|
+
* @param path The path to check.
|
|
29
|
+
*/
|
|
30
|
+
function hasTrailingSlash(path) {
|
|
31
|
+
return /\/$/.test(path);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @function isOutRoot
|
|
35
|
+
* @description Check if path is out of root.
|
|
36
|
+
* @param path The path to check.
|
|
37
|
+
* @param root The root path.
|
|
38
|
+
*/
|
|
39
|
+
function isOutRoot(path$1, root) {
|
|
40
|
+
path$1 = path.relative(root, path$1);
|
|
41
|
+
return /\.\.(?:[\\/]|$)/.test(path$1) || path.isAbsolute(path$1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
exports.hasTrailingSlash = hasTrailingSlash;
|
|
45
|
+
exports.isOutRoot = isOutRoot;
|
|
46
|
+
exports.unixify = unixify;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @package webpack-dev-service
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @version 0.10.1
|
|
5
|
+
* @author nuintun <nuintun@qq.com>
|
|
6
|
+
* @description A koa 2 middleware for webpack development and hot reloading.
|
|
7
|
+
* @see https://github.com/nuintun/webpack-dev-service#readme
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const url = require('url');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @module paths
|
|
16
|
+
*/
|
|
17
|
+
function getOutputPath(compilation) {
|
|
18
|
+
// The `output.path` is always present and always absolute.
|
|
19
|
+
const { path } = compilation.outputOptions;
|
|
20
|
+
// Get the path.
|
|
21
|
+
return compilation.getPath(path ? path : '');
|
|
22
|
+
}
|
|
23
|
+
function getPublicPath(compilation) {
|
|
24
|
+
const { publicPath } = compilation.outputOptions;
|
|
25
|
+
const path = compilation.getPath(publicPath ? publicPath : '');
|
|
26
|
+
// Get the path.
|
|
27
|
+
try {
|
|
28
|
+
return new url.URL(path).pathname;
|
|
29
|
+
} catch (_a) {
|
|
30
|
+
return path;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function getStats(stats) {
|
|
34
|
+
if (isMultiStatsMode(stats)) {
|
|
35
|
+
return stats.stats;
|
|
36
|
+
}
|
|
37
|
+
// Return the stats.
|
|
38
|
+
return [stats];
|
|
39
|
+
}
|
|
40
|
+
function isMultiStatsMode(stats) {
|
|
41
|
+
return 'stats' in stats;
|
|
42
|
+
}
|
|
43
|
+
function getPaths(stats) {
|
|
44
|
+
const paths = [];
|
|
45
|
+
const childStats = getStats(stats);
|
|
46
|
+
// Get the paths.
|
|
47
|
+
for (const { compilation } of childStats) {
|
|
48
|
+
paths.push([
|
|
49
|
+
// Output path.
|
|
50
|
+
getOutputPath(compilation),
|
|
51
|
+
// Public path.
|
|
52
|
+
getPublicPath(compilation)
|
|
53
|
+
]);
|
|
54
|
+
}
|
|
55
|
+
// Return the paths.
|
|
56
|
+
return paths;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
exports.getPaths = getPaths;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @package webpack-dev-service
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @version 0.10.1
|
|
5
|
+
* @author nuintun <nuintun@qq.com>
|
|
6
|
+
* @description A koa 2 middleware for webpack development and hot reloading.
|
|
7
|
+
* @see https://github.com/nuintun/webpack-dev-service#readme
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @module ready
|
|
14
|
+
*/
|
|
15
|
+
function ready({ stats, callbacks }, callback) {
|
|
16
|
+
if (stats) {
|
|
17
|
+
callback(stats);
|
|
18
|
+
} else {
|
|
19
|
+
callbacks.push(callback);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
exports.ready = ready;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @package webpack-dev-service
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @version 0.10.1
|
|
5
|
+
* @author nuintun <nuintun@qq.com>
|
|
6
|
+
* @description A koa 2 middleware for webpack development and hot reloading.
|
|
7
|
+
* @see https://github.com/nuintun/webpack-dev-service#readme
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const supportsColor = require('supports-color');
|
|
13
|
+
const utils = require('../../utils.cjs');
|
|
14
|
+
|
|
15
|
+
function _interopDefault(e) {
|
|
16
|
+
return e && e.__esModule ? e : { default: e };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const supportsColor__default = /*#__PURE__*/ _interopDefault(supportsColor);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @module setupHooks
|
|
23
|
+
*/
|
|
24
|
+
function normalizeStatsOptions(statsOptions) {
|
|
25
|
+
if (statsOptions == null) {
|
|
26
|
+
return { preset: 'normal' };
|
|
27
|
+
} else if (utils.isString(statsOptions)) {
|
|
28
|
+
return { preset: statsOptions };
|
|
29
|
+
} else if (utils.isBoolean(statsOptions)) {
|
|
30
|
+
return statsOptions ? { preset: 'normal' } : { preset: 'none' };
|
|
31
|
+
}
|
|
32
|
+
if (statsOptions.colors == null) {
|
|
33
|
+
const { stdout, stderr } = supportsColor__default.default;
|
|
34
|
+
statsOptions.colors = stdout !== false && stderr !== false;
|
|
35
|
+
}
|
|
36
|
+
return statsOptions;
|
|
37
|
+
}
|
|
38
|
+
function getStatsOptions(context) {
|
|
39
|
+
const { compiler } = context;
|
|
40
|
+
const { stats } = context.options;
|
|
41
|
+
if (stats) {
|
|
42
|
+
if (utils.isMultiCompilerMode(compiler)) {
|
|
43
|
+
return {
|
|
44
|
+
children: compiler.compilers.map(() => {
|
|
45
|
+
return normalizeStatsOptions(stats);
|
|
46
|
+
})
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
return normalizeStatsOptions(stats);
|
|
50
|
+
}
|
|
51
|
+
if (utils.isMultiCompilerMode(compiler)) {
|
|
52
|
+
return {
|
|
53
|
+
children: compiler.compilers.map(({ options }) => {
|
|
54
|
+
return normalizeStatsOptions(options.stats);
|
|
55
|
+
})
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return normalizeStatsOptions(compiler.options.stats);
|
|
59
|
+
}
|
|
60
|
+
function setupHooks(context) {
|
|
61
|
+
const { hooks } = context.compiler;
|
|
62
|
+
const statsOptions = getStatsOptions(context);
|
|
63
|
+
const invalid = () => {
|
|
64
|
+
// We are now in invalid state.
|
|
65
|
+
context.stats = null;
|
|
66
|
+
// Log compilation starting.
|
|
67
|
+
context.logger.log('compilation starting...');
|
|
68
|
+
};
|
|
69
|
+
const {
|
|
70
|
+
onCompilerDone = (stats, statsOptions) => {
|
|
71
|
+
const printedStats = stats.toString(statsOptions);
|
|
72
|
+
// Avoid extra empty line when `stats: 'none'`.
|
|
73
|
+
if (printedStats) {
|
|
74
|
+
context.logger.info(printedStats);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} = context.options;
|
|
78
|
+
const done = stats => {
|
|
79
|
+
// We are now on valid state
|
|
80
|
+
context.stats = stats;
|
|
81
|
+
// Do the stuff in nextTick, because bundle may be invalidated if a change happened while compiling.
|
|
82
|
+
process.nextTick(() => {
|
|
83
|
+
const { stats } = context;
|
|
84
|
+
// Check if still in valid state.
|
|
85
|
+
if (stats) {
|
|
86
|
+
// Call onCompilerDone.
|
|
87
|
+
onCompilerDone(stats, statsOptions);
|
|
88
|
+
// Callbacks.
|
|
89
|
+
const { callbacks } = context;
|
|
90
|
+
// Clear callbacks.
|
|
91
|
+
context.callbacks = [];
|
|
92
|
+
// Call callbacks.
|
|
93
|
+
for (const callback of callbacks) {
|
|
94
|
+
callback(stats);
|
|
95
|
+
}
|
|
96
|
+
// Log compilation finished.
|
|
97
|
+
context.logger.log('compilation finished');
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
};
|
|
101
|
+
hooks.done.tap(utils.PLUGIN_NAME, done);
|
|
102
|
+
hooks.invalid.tap(utils.PLUGIN_NAME, invalid);
|
|
103
|
+
hooks.watchRun.tap(utils.PLUGIN_NAME, invalid);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
exports.setupHooks = setupHooks;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @package webpack-dev-service
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @version 0.10.1
|
|
5
|
+
* @author nuintun <nuintun@qq.com>
|
|
6
|
+
* @description A koa 2 middleware for webpack development and hot reloading.
|
|
7
|
+
* @see https://github.com/nuintun/webpack-dev-service#readme
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const utils = require('../../utils.cjs');
|
|
13
|
+
const memfs = require('memfs');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @module setupOutputFileSystem
|
|
17
|
+
*/
|
|
18
|
+
function createMemfs() {
|
|
19
|
+
const volume = new memfs.Volume();
|
|
20
|
+
return memfs.createFsFromVolume(volume);
|
|
21
|
+
}
|
|
22
|
+
function setupOutputFileSystem(context) {
|
|
23
|
+
const { fs = createMemfs() } = context.options;
|
|
24
|
+
const compilers = utils.getCompilers(context.compiler);
|
|
25
|
+
for (const compiler of compilers) {
|
|
26
|
+
compiler.outputFileSystem = fs;
|
|
27
|
+
}
|
|
28
|
+
context.fs = fs;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
exports.setupOutputFileSystem = setupOutputFileSystem;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @package webpack-dev-service
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @version 0.10.1
|
|
5
|
+
* @author nuintun <nuintun@qq.com>
|
|
6
|
+
* @description A koa 2 middleware for webpack development and hot reloading.
|
|
7
|
+
* @see https://github.com/nuintun/webpack-dev-service#readme
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const utils = require('../../utils.cjs');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @module setupWatching
|
|
16
|
+
*/
|
|
17
|
+
function getWatching({ compiler, logger }) {
|
|
18
|
+
const isMulti = utils.isMultiCompilerMode(compiler);
|
|
19
|
+
if (!isMulti && compiler.watching) {
|
|
20
|
+
return compiler.watching;
|
|
21
|
+
}
|
|
22
|
+
const errorHandler = error => {
|
|
23
|
+
if (error) {
|
|
24
|
+
// For example - `writeToDisk` can throw an error and right now it is ends watching.
|
|
25
|
+
// We can improve that and keep watching active, but it is require API on webpack side.
|
|
26
|
+
// Let's implement that in webpack@5 because it is rare case.
|
|
27
|
+
logger.error(error);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
if (!isMulti) {
|
|
31
|
+
const { watchOptions } = compiler.options;
|
|
32
|
+
return compiler.watch(watchOptions, errorHandler);
|
|
33
|
+
}
|
|
34
|
+
const watchOptions = compiler.compilers.map(({ options }) => {
|
|
35
|
+
return options.watchOptions;
|
|
36
|
+
});
|
|
37
|
+
return compiler.watch(watchOptions, errorHandler);
|
|
38
|
+
}
|
|
39
|
+
function setupWatching(context) {
|
|
40
|
+
context.watching = getWatching(context);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
exports.setupWatching = setupWatching;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @package webpack-dev-service
|
|
3
|
+
* @license MIT
|
|
4
|
+
* @version 0.10.1
|
|
5
|
+
* @author nuintun <nuintun@qq.com>
|
|
6
|
+
* @description A koa 2 middleware for webpack development and hot reloading.
|
|
7
|
+
* @see https://github.com/nuintun/webpack-dev-service#readme
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const utils = require('../../utils.cjs');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @module setupWriteToDisk
|
|
18
|
+
*/
|
|
19
|
+
function getCompilerName({ options: { name } }) {
|
|
20
|
+
return name ? `compiler "${name}": ` : '';
|
|
21
|
+
}
|
|
22
|
+
function isAllowWrite(targetPath, filter) {
|
|
23
|
+
return utils.isFunction(filter) ? filter(targetPath) : filter === true;
|
|
24
|
+
}
|
|
25
|
+
function setupWriteToDisk(context) {
|
|
26
|
+
const { logger, options } = context;
|
|
27
|
+
const { writeToDisk: filter } = options;
|
|
28
|
+
const compilers = utils.getCompilers(context.compiler);
|
|
29
|
+
for (const compiler of compilers) {
|
|
30
|
+
compiler.hooks.assetEmitted.tapAsync(utils.PLUGIN_NAME, (_file, { targetPath, content }, callback) => {
|
|
31
|
+
if (!isAllowWrite(targetPath, filter)) {
|
|
32
|
+
return callback();
|
|
33
|
+
}
|
|
34
|
+
const dir = path.dirname(targetPath);
|
|
35
|
+
const name = getCompilerName(compiler);
|
|
36
|
+
return fs.mkdir(dir, { recursive: true }, error => {
|
|
37
|
+
if (error) {
|
|
38
|
+
logger.error(`${name}unable to write "${dir}" directory to disk:\n${error}`);
|
|
39
|
+
return callback(error);
|
|
40
|
+
}
|
|
41
|
+
fs.writeFile(targetPath, content, error => {
|
|
42
|
+
if (error) {
|
|
43
|
+
logger.error(`${name}unable to write "${targetPath}" asset to disk:\n${error}`);
|
|
44
|
+
return callback(error);
|
|
45
|
+
}
|
|
46
|
+
logger.log(`${name}asset written to disk: "${targetPath}"`);
|
|
47
|
+
return callback();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exports.setupWriteToDisk = setupWriteToDisk;
|