webpack-dev-service 0.7.2 → 0.8.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.
Files changed (71) hide show
  1. package/README.md +6 -10
  2. package/client/cjs/client.cjs +1 -1
  3. package/client/cjs/events.cjs +1 -1
  4. package/client/cjs/hot.cjs +1 -1
  5. package/client/cjs/index.cjs +1 -1
  6. package/client/cjs/main.cjs +1 -1
  7. package/client/cjs/ui/overlay.cjs +1 -1
  8. package/client/cjs/ui/progress.cjs +1 -1
  9. package/client/cjs/ui/utils.cjs +1 -1
  10. package/client/esm/client.js +1 -1
  11. package/client/esm/events.js +1 -1
  12. package/client/esm/hot.js +1 -1
  13. package/client/esm/index.js +1 -1
  14. package/client/esm/main.js +1 -1
  15. package/client/esm/ui/overlay.js +1 -1
  16. package/client/esm/ui/progress.js +1 -1
  17. package/client/esm/ui/utils.js +1 -1
  18. package/global.d.ts +2 -0
  19. package/package.json +13 -6
  20. package/server/cjs/dev/Files.cjs +394 -0
  21. package/server/cjs/dev/index.cjs +62 -0
  22. package/server/cjs/dev/middleware.cjs +69 -0
  23. package/server/cjs/dev/utils/boundary.cjs +42 -0
  24. package/server/cjs/dev/utils/common.cjs +98 -0
  25. package/server/cjs/dev/utils/compose.cjs +58 -0
  26. package/server/cjs/dev/utils/getPaths.cjs +71 -0
  27. package/server/cjs/dev/utils/http.cjs +69 -0
  28. package/server/cjs/dev/utils/ready.cjs +26 -0
  29. package/server/cjs/dev/utils/setupHooks.cjs +95 -0
  30. package/server/cjs/dev/utils/setupOutputFileSystem.cjs +64 -0
  31. package/server/cjs/dev/utils/setupWatching.cjs +43 -0
  32. package/server/cjs/dev/utils/setupWriteToDisk.cjs +62 -0
  33. package/server/cjs/{hot.cjs → hot/Socket.cjs} +6 -20
  34. package/server/cjs/hot/index.cjs +36 -0
  35. package/server/cjs/index.cjs +11 -15
  36. package/server/esm/dev/Files.js +384 -0
  37. package/server/esm/dev/index.js +60 -0
  38. package/server/esm/dev/middleware.js +67 -0
  39. package/server/esm/dev/utils/boundary.js +40 -0
  40. package/server/esm/dev/utils/common.js +98 -0
  41. package/server/esm/dev/utils/compose.js +56 -0
  42. package/server/esm/dev/utils/getPaths.js +69 -0
  43. package/server/esm/dev/utils/http.js +65 -0
  44. package/server/esm/dev/utils/ready.js +24 -0
  45. package/server/esm/dev/utils/setupHooks.js +87 -0
  46. package/server/esm/dev/utils/setupOutputFileSystem.js +62 -0
  47. package/server/esm/dev/utils/setupWatching.js +41 -0
  48. package/server/esm/dev/utils/setupWriteToDisk.js +60 -0
  49. package/server/esm/{hot.js → hot/Socket.js} +6 -20
  50. package/server/esm/hot/index.js +34 -0
  51. package/server/esm/index.js +11 -9
  52. package/types/server/dev/Files.d.ts +83 -0
  53. package/types/server/dev/index.d.ts +8 -0
  54. package/types/server/dev/interface.d.ts +46 -0
  55. package/types/server/dev/middleware.d.ts +6 -0
  56. package/types/server/dev/utils/boundary.d.ts +8 -0
  57. package/types/server/dev/utils/common.d.ts +44 -0
  58. package/types/server/dev/utils/compose.d.ts +18 -0
  59. package/types/server/dev/utils/getPaths.d.ts +10 -0
  60. package/types/server/dev/utils/http.d.ts +22 -0
  61. package/types/server/dev/utils/ready.d.ts +5 -0
  62. package/types/server/dev/utils/setupHooks.d.ts +5 -0
  63. package/types/server/dev/utils/setupOutputFileSystem.d.ts +5 -0
  64. package/types/server/dev/utils/setupWatching.d.ts +5 -0
  65. package/types/server/dev/utils/setupWriteToDisk.d.ts +5 -0
  66. package/types/server/hot/Socket.d.ts +27 -0
  67. package/types/server/{hot.d.ts → hot/index.d.ts} +7 -10
  68. package/types/server/index.d.ts +4 -4
  69. package/server/cjs/dev.cjs +0 -50
  70. package/server/esm/dev.js +0 -42
  71. package/types/server/dev.d.ts +0 -17
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.8.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
+ import Files from './Files.js';
11
+ import { decodeURI } from './utils/common.js';
12
+ import { getPaths } from './utils/getPaths.js';
13
+
14
+ /**
15
+ * @module middleware
16
+ */
17
+ const cache = new WeakMap();
18
+ async function getFilesInstances(context, name) {
19
+ const cached = cache.get(context.compiler);
20
+ if (cached != null) {
21
+ return cached;
22
+ }
23
+ const { options } = context;
24
+ const instances = [];
25
+ const paths = await getPaths(context, name);
26
+ for (const { outputPath, publicPath } of paths) {
27
+ instances.push({
28
+ publicPath,
29
+ files: new Files(outputPath, {
30
+ etag: options.etag,
31
+ headers: options.headers,
32
+ fs: context.outputFileSystem,
33
+ acceptRanges: options.acceptRanges,
34
+ cacheControl: options.cacheControl,
35
+ lastModified: options.lastModified
36
+ })
37
+ });
38
+ }
39
+ return instances;
40
+ }
41
+ function middleware(context) {
42
+ return async (ctx, next) => {
43
+ const path = decodeURI(ctx.path);
44
+ // Path -1 or null byte(s)
45
+ if (path === -1 || path.includes('\0')) {
46
+ return ctx.throw(400);
47
+ }
48
+ let respond = false;
49
+ const instances = await getFilesInstances(context, path);
50
+ for (const { files, publicPath } of instances) {
51
+ if (path.startsWith(publicPath)) {
52
+ ctx.path = path.slice(publicPath.length);
53
+ respond = await files.response(ctx);
54
+ if (respond) {
55
+ return;
56
+ } else {
57
+ ctx.path = path;
58
+ }
59
+ }
60
+ }
61
+ if (!respond) {
62
+ await next();
63
+ }
64
+ };
65
+ }
66
+
67
+ export { middleware };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.8.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
+ /**
11
+ * @module boundary
12
+ */
13
+ // prettier-ignore
14
+ const CHARS = [
15
+ // 0-9
16
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
17
+ // A-M
18
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
19
+ // N-Z
20
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
21
+ // a-m
22
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
23
+ // n-z
24
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
25
+ ];
26
+ /**
27
+ * @function generate
28
+ * @description Generate a boundary.
29
+ */
30
+ function generate() {
31
+ let boundary = '';
32
+ // Create boundary.
33
+ for (let i = 0; i < 38; i++) {
34
+ boundary += CHARS[Math.floor(Math.random() * 62)];
35
+ }
36
+ // Return boundary.
37
+ return boundary;
38
+ }
39
+
40
+ export { generate };
@@ -0,0 +1,98 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.8.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
+ import { relative, isAbsolute } from 'path';
11
+
12
+ /**
13
+ * @module common
14
+ */
15
+ const { toString } = Object.prototype;
16
+ const PLUGIN_NAME = 'webpack-dev-service';
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 decodeURI
27
+ * @description Decode URI component.
28
+ * @param URI The URI to decode.
29
+ */
30
+ function decodeURI(URI) {
31
+ try {
32
+ return decodeURIComponent(URI);
33
+ } catch (_a) {
34
+ return -1;
35
+ }
36
+ }
37
+ /**
38
+ * @function hasTrailingSlash
39
+ * @description Check if path has trailing slash.
40
+ * @param path The path to check.
41
+ */
42
+ function hasTrailingSlash(path) {
43
+ return /\/$/.test(path);
44
+ }
45
+ function isString(value) {
46
+ return toString.call(value) === '[object String]';
47
+ }
48
+ function isBoolean(value) {
49
+ return toString.call(value) === '[object Boolean]';
50
+ }
51
+ function isFunction(value) {
52
+ return typeof value === 'function';
53
+ }
54
+ /**
55
+ * @function isOutRoot
56
+ * @description Check if path is out of root.
57
+ * @param path The path to check.
58
+ * @param root The root path.
59
+ */
60
+ function isOutRoot(path, root) {
61
+ path = relative(root, path);
62
+ return /\.\.(?:[\\/]|$)/.test(path) || isAbsolute(path);
63
+ }
64
+ function getCompilers(compiler) {
65
+ if (isMultiCompilerMode(compiler)) {
66
+ return compiler.compilers;
67
+ }
68
+ return [compiler];
69
+ }
70
+ /**
71
+ * @function fstat
72
+ * @description Get file stats.
73
+ * @param path The file path.
74
+ */
75
+ function fstat(fs, path) {
76
+ return new Promise((resolve, reject) => {
77
+ fs.stat(path, (error, stats) => {
78
+ error ? reject(error) : resolve(stats);
79
+ });
80
+ });
81
+ }
82
+ function isMultiCompilerMode(compiler) {
83
+ return 'compilers' in compiler;
84
+ }
85
+
86
+ export {
87
+ PLUGIN_NAME,
88
+ decodeURI,
89
+ fstat,
90
+ getCompilers,
91
+ hasTrailingSlash,
92
+ isBoolean,
93
+ isFunction,
94
+ isMultiCompilerMode,
95
+ isOutRoot,
96
+ isString,
97
+ unixify
98
+ };
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.8.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
+ /**
11
+ * @module compose
12
+ */
13
+ /**
14
+ * @function dispatch
15
+ * @param middlewares 中间件数组
16
+ * @param index 要执行的中间件索引
17
+ * @param stack 调用栈信息
18
+ * @param context 执行上下文
19
+ * @param [next] 下一个中间件
20
+ */
21
+ async function dispatch(middlewares, index, stack, context, next) {
22
+ if (index <= stack.index) {
23
+ throw new Error('next() called multiple times');
24
+ }
25
+ stack.index = index;
26
+ const { length } = middlewares;
27
+ if (index <= length) {
28
+ if (index < length) {
29
+ const middleware = middlewares[index];
30
+ await middleware(context, () => {
31
+ return dispatch(middlewares, index + 1, stack, context, next);
32
+ });
33
+ } else if (next) {
34
+ await next();
35
+ }
36
+ }
37
+ }
38
+ /**
39
+ * @function compose
40
+ * @description 生成融合中间件
41
+ * @param middlewares 中间件数组
42
+ */
43
+ function compose(...middlewares) {
44
+ /**
45
+ * @function middleware
46
+ * @description 融合中间件
47
+ * @param context 执行上下文
48
+ * @param [next] 下一个中间件
49
+ */
50
+ return (context, next) => {
51
+ const stack = { index: -1 };
52
+ return dispatch(middlewares, 0, stack, context, next);
53
+ };
54
+ }
55
+
56
+ export { compose };
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.8.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
+ import { URL } from 'url';
11
+ import { ready } from './ready.js';
12
+
13
+ /**
14
+ * @module getPaths
15
+ */
16
+ const cache = new WeakMap();
17
+ function getOutputPath(compilation) {
18
+ const { path } = compilation.outputOptions;
19
+ return compilation.getPath(path != null ? path : '');
20
+ }
21
+ function getPublicPath(compilation) {
22
+ const { publicPath } = compilation.outputOptions;
23
+ const path = compilation.getPath(publicPath != null ? publicPath : '');
24
+ try {
25
+ return new URL(path).pathname;
26
+ } catch (_a) {
27
+ return path;
28
+ }
29
+ }
30
+ function getStats(stats) {
31
+ if (stats == null) {
32
+ return [];
33
+ }
34
+ if (isMultiStatsMode(stats)) {
35
+ return stats.stats;
36
+ }
37
+ return [stats];
38
+ }
39
+ function isMultiStatsMode(stats) {
40
+ return 'stats' in stats;
41
+ }
42
+ function getPaths(context, name) {
43
+ return new Promise(resolve => {
44
+ const { compiler } = context;
45
+ const paths = cache.get(compiler);
46
+ if (paths != null) {
47
+ resolve(paths);
48
+ } else {
49
+ ready(
50
+ context,
51
+ stats => {
52
+ const paths = [];
53
+ const childStats = getStats(stats);
54
+ for (const { compilation } of childStats) {
55
+ // The `output.path` is always present and always absolute
56
+ const outputPath = getOutputPath(compilation);
57
+ const publicPath = getPublicPath(compilation);
58
+ paths.push({ outputPath, publicPath });
59
+ }
60
+ cache.set(compiler, paths);
61
+ resolve(paths);
62
+ },
63
+ name
64
+ );
65
+ }
66
+ });
67
+ }
68
+
69
+ export { getPaths };
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.8.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
+ /**
11
+ * @method http
12
+ */
13
+ /**
14
+ * @function parseTokens
15
+ * @description Parse HTTP tokens.
16
+ * @param value The tokens value string.
17
+ */
18
+ function parseTokens(value) {
19
+ let end = 0;
20
+ let start = 0;
21
+ let tokens = [];
22
+ // Gather tokens.
23
+ for (let i = 0, length = value.length; i < length; i++) {
24
+ switch (value.charCodeAt(i)) {
25
+ case 0x20:
26
+ // ' '.
27
+ if (start === end) {
28
+ start = end = i + 1;
29
+ }
30
+ break;
31
+ case 0x2c:
32
+ // ','.
33
+ tokens.push(value.substring(start, end));
34
+ start = end = i + 1;
35
+ break;
36
+ default:
37
+ end = i + 1;
38
+ break;
39
+ }
40
+ }
41
+ // Final token.
42
+ tokens.push(value.substring(start, end));
43
+ return tokens;
44
+ }
45
+ /**
46
+ * @function isETag
47
+ * @description Check if etag is valid.
48
+ * @param value The value to check.
49
+ */
50
+ function isETag(value) {
51
+ return /^(?:W\/)?"[\s\S]+"$/.test(value);
52
+ }
53
+ /**
54
+ * @function isETagFresh
55
+ * @description Check if etag is fresh.
56
+ * @param match The match value.
57
+ * @param etag The etag value.
58
+ */
59
+ function isETagFresh(match, etag) {
60
+ return parseTokens(match).some(match => {
61
+ return match === etag || match === 'W/' + etag || 'W/' + match === etag;
62
+ });
63
+ }
64
+
65
+ export { isETag, isETagFresh, parseTokens };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.8.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
+ /**
11
+ * @method ready
12
+ */
13
+ function ready(context, callback, name) {
14
+ if (context.state) {
15
+ callback(context.stats);
16
+ } else {
17
+ context.callbacks.push(callback);
18
+ if (name) {
19
+ context.logger.info(`wait until bundle finished: ${name}`);
20
+ }
21
+ }
22
+ }
23
+
24
+ export { ready };
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.8.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
+ import supportsColor from 'supports-color';
11
+ import { PLUGIN_NAME, isMultiCompilerMode, isString, isBoolean } from './common.js';
12
+
13
+ /**
14
+ * @module setupHooks
15
+ */
16
+ function normalizeStatsOptions(statsOptions) {
17
+ if (statsOptions == null) {
18
+ return { preset: 'normal' };
19
+ } else if (isString(statsOptions)) {
20
+ return { preset: statsOptions };
21
+ } else if (isBoolean(statsOptions)) {
22
+ return statsOptions ? { preset: 'normal' } : { preset: 'none' };
23
+ }
24
+ if (statsOptions.colors == null) {
25
+ const { stdout, stderr } = supportsColor;
26
+ statsOptions.colors = stdout !== false && stderr !== false;
27
+ }
28
+ return statsOptions;
29
+ }
30
+ function getStatsOptions(context) {
31
+ const { compiler } = context;
32
+ const { stats } = context.options;
33
+ if (stats != null) {
34
+ if (!isMultiCompilerMode(compiler)) {
35
+ return normalizeStatsOptions(stats);
36
+ }
37
+ return {
38
+ children: compiler.compilers.map(() => normalizeStatsOptions(stats))
39
+ };
40
+ }
41
+ if (!isMultiCompilerMode(compiler)) {
42
+ return normalizeStatsOptions(compiler.options.stats);
43
+ }
44
+ return {
45
+ children: compiler.compilers.map(({ options }) => normalizeStatsOptions(options.stats))
46
+ };
47
+ }
48
+ function setupHooks(context) {
49
+ function invalid() {
50
+ if (context.state) {
51
+ context.logger.log('Compilation starting...');
52
+ }
53
+ // We are now in invalid state
54
+ context.stats = null;
55
+ context.state = false;
56
+ }
57
+ function done(stats) {
58
+ // We are now on valid state
59
+ context.state = true;
60
+ context.stats = stats;
61
+ // Do the stuff in nextTick, because bundle may be invalidated if a change happened while compiling
62
+ process.nextTick(() => {
63
+ const { state } = context;
64
+ // Check if still in valid state
65
+ if (state) {
66
+ const { logger, callbacks } = context;
67
+ logger.log('Compilation finished');
68
+ context.callbacks = [];
69
+ for (const callback of callbacks) {
70
+ callback(stats);
71
+ }
72
+ const statsOptions = getStatsOptions(context);
73
+ const printedStats = stats.toString(statsOptions);
74
+ // Avoid extra empty line when `stats: 'none'`
75
+ if (printedStats) {
76
+ logger.log(printedStats);
77
+ }
78
+ }
79
+ });
80
+ }
81
+ const { hooks } = context.compiler;
82
+ hooks.done.tap(PLUGIN_NAME, done);
83
+ hooks.invalid.tap(PLUGIN_NAME, invalid);
84
+ hooks.watchRun.tap(PLUGIN_NAME, invalid);
85
+ }
86
+
87
+ export { setupHooks };
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.8.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
+ import { Volume, createFsFromVolume } from 'memfs';
11
+ import { getCompilers, isFunction, isMultiCompilerMode } from './common.js';
12
+
13
+ /**
14
+ * @module setupOutputFileSystem
15
+ */
16
+ function createMemfs() {
17
+ const volume = new Volume();
18
+ return createFsFromVolume(volume);
19
+ }
20
+ function hasReadStream(fs) {
21
+ return isFunction(fs.createReadStream);
22
+ }
23
+ function getOutputFileSystem({ options, compiler }) {
24
+ if (options.outputFileSystem) {
25
+ return options.outputFileSystem;
26
+ }
27
+ if (options.writeToDisk !== true) {
28
+ return createMemfs();
29
+ }
30
+ if (isMultiCompilerMode(compiler)) {
31
+ const { compilers } = compiler;
32
+ for (const compiler of compilers) {
33
+ if ('devServer' in compiler) {
34
+ if (compiler.outputFileSystem) {
35
+ return compiler.outputFileSystem;
36
+ }
37
+ }
38
+ }
39
+ if (compiler.outputFileSystem) {
40
+ return compiler.outputFileSystem;
41
+ }
42
+ for (const compiler of compilers) {
43
+ if (compiler.outputFileSystem) {
44
+ return compiler.outputFileSystem;
45
+ }
46
+ }
47
+ }
48
+ return createMemfs();
49
+ }
50
+ function setupOutputFileSystem(context) {
51
+ const compilers = getCompilers(context.compiler);
52
+ const outputFileSystem = getOutputFileSystem(context);
53
+ if (!hasReadStream(outputFileSystem)) {
54
+ throw new Error('Compiler outputFileSystem must support createReadStream');
55
+ }
56
+ for (const compiler of compilers) {
57
+ compiler.outputFileSystem = outputFileSystem;
58
+ }
59
+ context.outputFileSystem = outputFileSystem;
60
+ }
61
+
62
+ export { setupOutputFileSystem };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.8.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
+ import { isMultiCompilerMode } from './common.js';
11
+
12
+ /**
13
+ * @module setupWatching
14
+ */
15
+ function getWatching({ compiler, logger }) {
16
+ const isMulti = isMultiCompilerMode(compiler);
17
+ if (!isMulti && compiler.watching) {
18
+ return compiler.watching;
19
+ }
20
+ const errorHandler = error => {
21
+ if (error) {
22
+ // For example - `writeToDisk` can throw an error and right now it is ends watching.
23
+ // We can improve that and keep watching active, but it is require API on webpack side.
24
+ // Let's implement that in webpack@5 because it is rare case.
25
+ logger.error(error);
26
+ }
27
+ };
28
+ if (!isMulti) {
29
+ const { watchOptions } = compiler.options;
30
+ return compiler.watch(watchOptions, errorHandler);
31
+ }
32
+ const watchOptions = compiler.compilers.map(({ options }) => {
33
+ return options.watchOptions;
34
+ });
35
+ return compiler.watch(watchOptions, errorHandler);
36
+ }
37
+ function setupWatching(context) {
38
+ context.watching = getWatching(context);
39
+ }
40
+
41
+ export { setupWatching };
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @package webpack-dev-service
3
+ * @license MIT
4
+ * @version 0.8.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
+ import { dirname } from 'path';
11
+ import { mkdir, writeFile } from 'fs';
12
+ import { getCompilers, PLUGIN_NAME, isFunction } from './common.js';
13
+
14
+ /**
15
+ * @module setupWriteToDisk
16
+ */
17
+ const assetEmitted = Symbol('assetEmitted');
18
+ function getCompilerName({ options: { name } }) {
19
+ return name ? `Child "${name}": ` : '';
20
+ }
21
+ function isAllowWrite(targetPath, filter) {
22
+ return filter && isFunction(filter) ? filter(targetPath) : true;
23
+ }
24
+ function setupWriteToDisk(context) {
25
+ const { logger, options } = context;
26
+ const { writeToDisk: filter } = options;
27
+ const compilers = getCompilers(context.compiler);
28
+ for (const compiler of compilers) {
29
+ const { hooks } = compiler;
30
+ hooks.emit.tap(PLUGIN_NAME, () => {
31
+ if (!compiler[assetEmitted]) {
32
+ hooks.assetEmitted.tapAsync(PLUGIN_NAME, (_file, { targetPath, content }, callback) => {
33
+ if (!isAllowWrite(targetPath, filter)) {
34
+ return callback();
35
+ }
36
+ const dir = dirname(targetPath);
37
+ const name = getCompilerName(compiler);
38
+ return mkdir(dir, { recursive: true }, mkdirError => {
39
+ if (mkdirError) {
40
+ logger.error(`${name}Unable to write "${dir}" directory to disk:\n${mkdirError}`);
41
+ return callback(mkdirError);
42
+ }
43
+ writeFile(targetPath, content, writeFileError => {
44
+ if (writeFileError) {
45
+ logger.error(`${name}Unable to write "${targetPath}" asset to disk:\n${writeFileError}`);
46
+ return callback(writeFileError);
47
+ }
48
+ logger.log(`${name}Asset written to disk: "${targetPath}"`);
49
+ return callback();
50
+ });
51
+ });
52
+ });
53
+ // Set asset emitted to true
54
+ compiler[assetEmitted] = true;
55
+ }
56
+ });
57
+ }
58
+ }
59
+
60
+ export { setupWriteToDisk };