webpack-dev-service 0.13.2 → 0.14.0

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 (148) hide show
  1. package/README.md +9 -8
  2. package/cjs/client/client.cjs +24 -9
  3. package/cjs/client/client.d.cts +14 -0
  4. package/cjs/client/events.cjs +1 -1
  5. package/cjs/client/events.d.cts +28 -0
  6. package/cjs/client/hot.cjs +19 -21
  7. package/cjs/client/hot.d.cts +16 -0
  8. package/cjs/client/index.cjs +1 -1
  9. package/cjs/client/index.d.cts +4 -0
  10. package/cjs/client/main.cjs +4 -3
  11. package/cjs/client/main.d.cts +4 -0
  12. package/cjs/client/ui/Overlay.cjs +1 -1
  13. package/cjs/client/ui/Overlay.d.cts +12 -0
  14. package/cjs/client/ui/Progress.cjs +1 -1
  15. package/cjs/client/ui/Progress.d.cts +12 -0
  16. package/cjs/client/ui/utils.cjs +1 -1
  17. package/cjs/client/ui/utils.d.cts +15 -0
  18. package/cjs/server/compose.cjs +13 -12
  19. package/cjs/server/compose.d.cts +18 -0
  20. package/cjs/server/dev/ReadStream.cjs +1 -1
  21. package/cjs/server/dev/ReadStream.d.cts +43 -0
  22. package/cjs/server/dev/Service.cjs +1 -1
  23. package/cjs/server/dev/Service.d.cts +48 -0
  24. package/cjs/server/dev/index.cjs +1 -1
  25. package/cjs/server/dev/index.d.cts +8 -0
  26. package/cjs/server/dev/interface.d.cts +38 -0
  27. package/cjs/server/dev/middleware.cjs +1 -1
  28. package/cjs/server/dev/middleware.d.cts +6 -0
  29. package/cjs/server/dev/utils/fs.cjs +1 -1
  30. package/cjs/server/dev/utils/fs.d.cts +24 -0
  31. package/cjs/server/dev/utils/hash.cjs +1 -1
  32. package/cjs/server/dev/utils/hash.d.cts +9 -0
  33. package/cjs/server/dev/utils/http.cjs +1 -1
  34. package/cjs/server/dev/utils/http.d.cts +37 -0
  35. package/cjs/server/dev/utils/path.cjs +1 -1
  36. package/cjs/server/dev/utils/path.d.cts +22 -0
  37. package/cjs/server/dev/utils/paths.cjs +1 -1
  38. package/cjs/server/dev/utils/paths.d.cts +7 -0
  39. package/cjs/server/dev/utils/ready.cjs +1 -1
  40. package/cjs/server/dev/utils/ready.d.cts +5 -0
  41. package/cjs/server/dev/utils/setupHooks.cjs +2 -5
  42. package/cjs/server/dev/utils/setupHooks.d.cts +5 -0
  43. package/cjs/server/dev/utils/setupOutputFileSystem.cjs +1 -1
  44. package/cjs/server/dev/utils/setupOutputFileSystem.d.cts +5 -0
  45. package/cjs/server/dev/utils/setupWatching.cjs +1 -1
  46. package/cjs/server/dev/utils/setupWatching.d.cts +5 -0
  47. package/cjs/server/dev/utils/setupWriteToDisk.cjs +2 -2
  48. package/cjs/server/dev/utils/setupWriteToDisk.d.cts +5 -0
  49. package/cjs/server/hot/Message.d.cts +49 -0
  50. package/cjs/server/hot/Socket.cjs +109 -97
  51. package/cjs/server/hot/Socket.d.cts +11 -0
  52. package/cjs/server/hot/index.cjs +3 -10
  53. package/cjs/server/hot/index.d.cts +8 -0
  54. package/cjs/server/hot/interface.d.cts +22 -0
  55. package/cjs/server/hot/utils.cjs +11 -36
  56. package/cjs/server/hot/utils.d.cts +12 -0
  57. package/cjs/server/index.cjs +8 -2
  58. package/cjs/server/index.d.cts +17 -0
  59. package/cjs/server/interface.d.cts +14 -0
  60. package/cjs/server/schema.cjs +1 -1
  61. package/cjs/server/schema.d.cts +7 -0
  62. package/cjs/server/utils.cjs +1 -5
  63. package/cjs/server/utils.d.cts +11 -0
  64. package/esm/client/client.d.ts +14 -0
  65. package/esm/client/client.js +25 -10
  66. package/esm/client/events.d.ts +28 -0
  67. package/esm/client/events.js +1 -1
  68. package/esm/client/hot.d.ts +16 -0
  69. package/esm/client/hot.js +19 -19
  70. package/esm/client/index.d.ts +4 -0
  71. package/esm/client/index.js +1 -1
  72. package/esm/client/main.d.ts +4 -0
  73. package/esm/client/main.js +4 -3
  74. package/esm/client/ui/Overlay.d.ts +12 -0
  75. package/esm/client/ui/Overlay.js +1 -1
  76. package/esm/client/ui/Progress.d.ts +12 -0
  77. package/esm/client/ui/Progress.js +1 -1
  78. package/esm/client/ui/utils.d.ts +15 -0
  79. package/esm/client/ui/utils.js +1 -1
  80. package/esm/server/compose.d.ts +18 -0
  81. package/esm/server/compose.js +13 -12
  82. package/esm/server/dev/ReadStream.d.ts +43 -0
  83. package/esm/server/dev/ReadStream.js +1 -1
  84. package/esm/server/dev/Service.d.ts +48 -0
  85. package/esm/server/dev/Service.js +1 -1
  86. package/esm/server/dev/index.d.ts +8 -0
  87. package/esm/server/dev/index.js +1 -1
  88. package/esm/server/dev/interface.d.ts +38 -0
  89. package/esm/server/dev/middleware.d.ts +6 -0
  90. package/esm/server/dev/middleware.js +1 -1
  91. package/esm/server/dev/utils/fs.d.ts +24 -0
  92. package/esm/server/dev/utils/fs.js +1 -1
  93. package/esm/server/dev/utils/hash.d.ts +9 -0
  94. package/esm/server/dev/utils/hash.js +1 -1
  95. package/esm/server/dev/utils/http.d.ts +37 -0
  96. package/esm/server/dev/utils/http.js +1 -1
  97. package/esm/server/dev/utils/path.d.ts +22 -0
  98. package/esm/server/dev/utils/path.js +1 -1
  99. package/esm/server/dev/utils/paths.d.ts +7 -0
  100. package/esm/server/dev/utils/paths.js +1 -1
  101. package/esm/server/dev/utils/ready.d.ts +5 -0
  102. package/esm/server/dev/utils/ready.js +1 -1
  103. package/esm/server/dev/utils/setupHooks.d.ts +5 -0
  104. package/esm/server/dev/utils/setupHooks.js +2 -5
  105. package/esm/server/dev/utils/setupOutputFileSystem.d.ts +5 -0
  106. package/esm/server/dev/utils/setupOutputFileSystem.js +1 -1
  107. package/esm/server/dev/utils/setupWatching.d.ts +5 -0
  108. package/esm/server/dev/utils/setupWatching.js +1 -1
  109. package/esm/server/dev/utils/setupWriteToDisk.d.ts +5 -0
  110. package/esm/server/dev/utils/setupWriteToDisk.js +2 -2
  111. package/{types/client → esm/server/hot}/Message.d.ts +15 -7
  112. package/esm/server/hot/Socket.d.ts +11 -0
  113. package/esm/server/hot/Socket.js +110 -98
  114. package/esm/server/hot/index.d.ts +8 -0
  115. package/esm/server/hot/index.js +3 -10
  116. package/esm/server/hot/interface.d.ts +22 -0
  117. package/esm/server/hot/utils.d.ts +12 -0
  118. package/esm/server/hot/utils.js +12 -38
  119. package/esm/server/index.d.ts +17 -0
  120. package/esm/server/index.js +8 -2
  121. package/esm/server/interface.d.ts +14 -0
  122. package/esm/server/schema.d.ts +7 -0
  123. package/esm/server/schema.js +1 -1
  124. package/esm/server/utils.d.ts +11 -0
  125. package/esm/server/utils.js +2 -5
  126. package/global.d.ts +2 -0
  127. package/package.json +20 -19
  128. package/types/client/client.d.ts +2 -1
  129. package/types/client/events.d.ts +2 -9
  130. package/types/client/hot.d.ts +3 -14
  131. package/types/server/compose.d.ts +2 -2
  132. package/types/server/dev/index.d.ts +1 -1
  133. package/types/server/dev/interface.d.ts +2 -2
  134. package/types/server/dev/utils/fs.d.ts +2 -4
  135. package/types/server/dev/utils/paths.d.ts +1 -1
  136. package/types/server/dev/utils/ready.d.ts +1 -1
  137. package/types/server/dev/utils/setupHooks.d.ts +1 -1
  138. package/types/server/dev/utils/setupOutputFileSystem.d.ts +1 -1
  139. package/types/server/dev/utils/setupWatching.d.ts +1 -1
  140. package/types/server/dev/utils/setupWriteToDisk.d.ts +1 -1
  141. package/types/server/hot/Message.d.ts +49 -0
  142. package/types/server/hot/Socket.d.ts +1 -4
  143. package/types/server/hot/index.d.ts +4 -4
  144. package/types/server/hot/interface.d.ts +8 -6
  145. package/types/server/hot/utils.d.ts +4 -4
  146. package/types/server/index.d.ts +6 -26
  147. package/types/server/interface.d.ts +3 -0
  148. package/types/server/utils.d.ts +0 -1
@@ -1,71 +1,65 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
8
8
  */
9
9
 
10
10
  import webpack from 'webpack';
11
+ import { v7 } from 'uuid';
11
12
  import { Buffer } from 'node:buffer';
12
- import { fileURLToPath } from 'node:url';
13
13
  import { resolve, dirname } from 'node:path';
14
+ import { fileURLToPath, URL } from 'node:url';
14
15
  import WebSocket, { WebSocketServer } from 'ws';
15
16
  import { PLUGIN_NAME, getCompilers } from '../utils.js';
16
- import { getOptions, getStatsOptions, getTimestamp, isUpgradable, hasIssues } from './utils.js';
17
+ import { getOptions, getStatsOptions, getTimestamp, BASE_URL, hasIssues, isUpgradable } from './utils.js';
17
18
 
18
19
  /**
19
20
  * @module Socket
20
21
  */
21
22
  function entrypoint() {
22
23
  const filename = import.meta.url;
23
- try {
24
- return dirname(fileURLToPath(filename));
25
- } catch {
26
- return dirname(filename);
27
- }
24
+ return dirname(fileURLToPath(filename));
28
25
  }
29
26
  const client = resolve(entrypoint(), '../../client/main.js');
30
27
  class Socket {
31
28
  // Readonly props.
32
29
  #logger;
33
- #compiler;
34
30
  #server;
35
31
  #options;
36
- // Mutable props.
37
- #percentage = -1;
38
- #stats = null;
39
32
  constructor(compiler, options) {
40
- this.#compiler = compiler;
41
33
  this.#options = getOptions(options);
42
34
  this.#logger = compiler.getInfrastructureLogger(PLUGIN_NAME);
43
35
  this.#server = new WebSocketServer({ noServer: true, path: this.#options.path });
44
- this.#setupWss();
45
- this.#setupHooks();
46
- this.#setupPlugins();
47
- }
48
- #setupWss() {
49
- const logger = this.#logger;
50
- const server = this.#server;
51
- server.on('connection', client => {
52
- const stats = this.#stats;
53
- logger.log('client connected');
54
- client.on('close', () => {
55
- logger.log('client disconnected');
56
- });
57
- if (stats) {
58
- this.#broadcastStats([client], stats);
59
- }
60
- });
61
- server.on('error', error => {
62
- logger.error(error);
63
- });
36
+ const compilers = getCompilers(compiler);
37
+ const contexts = new Map();
38
+ for (const compiler of compilers) {
39
+ const uuid = v7();
40
+ const context = {
41
+ uuid,
42
+ stats: null,
43
+ percentage: -1,
44
+ clients: new Set()
45
+ };
46
+ contexts.set(uuid, context);
47
+ this.#setupHooks(compiler, context);
48
+ this.#setupPlugins(compiler, context);
49
+ }
50
+ this.#setupWss(contexts);
64
51
  }
65
- #setupHooks() {
66
- const compiler = this.#compiler;
52
+ #setupHooks(compiler, context) {
67
53
  const { hooks } = compiler;
68
54
  const statsOptions = getStatsOptions(compiler);
55
+ hooks.invalid.tap(PLUGIN_NAME, (path, timestamp) => {
56
+ // Set stats to null.
57
+ context.stats = null;
58
+ // Reset percentage.
59
+ context.percentage = -1;
60
+ // Broadcast invalid.
61
+ this.#broadcast(context.clients, 'invalid', { path, timestamp });
62
+ });
69
63
  hooks.done.tap(PLUGIN_NAME, stats => {
70
64
  // Get json stats.
71
65
  const jsonStats = stats.toJson(statsOptions);
@@ -74,66 +68,102 @@ class Socket {
74
68
  jsonStats.builtAt = getTimestamp(jsonStats);
75
69
  }
76
70
  // Cache stats.
77
- this.#stats = jsonStats;
71
+ context.stats = jsonStats;
78
72
  // Do the stuff in nextTick, because bundle may be invalidated if a change happened while compiling.
79
73
  process.nextTick(() => {
80
- const stats = this.#stats;
74
+ const { stats } = context;
81
75
  // Broadcast stats.
82
76
  if (stats) {
83
- this.#broadcastStats(this.clients(), stats);
77
+ this.#broadcastStats(context.clients, stats);
84
78
  }
85
79
  });
86
80
  });
87
- hooks.invalid.tap(PLUGIN_NAME, (path, timestamp) => {
88
- // Set stats to null.
89
- this.#stats = null;
90
- // Reset percentage.
91
- this.#percentage = -1;
92
- // Broadcast invalid.
93
- this.broadcast(this.clients(), 'invalid', { path, timestamp });
94
- });
95
81
  }
96
- #setupPlugins() {
82
+ #setupPlugins(compiler, context) {
97
83
  const options = this.#options;
98
- const compiler = this.#compiler;
99
- const compilers = getCompilers(compiler);
84
+ const params = new URLSearchParams();
85
+ params.set('uuid', context.uuid);
86
+ params.set('path', options.path);
87
+ const { wss } = options;
88
+ if (wss != null) {
89
+ params.set('wss', wss ? 'true' : 'false');
90
+ }
91
+ params.set('name', compiler.name || 'rspack');
92
+ params.set('hmr', options.hmr ? 'true' : 'false');
93
+ params.set('reload', options.reload ? 'true' : 'false');
94
+ params.set('overlay', options.overlay ? 'true' : 'false');
95
+ params.set('progress', options.progress ? 'true' : 'false');
100
96
  const plugins = [
101
- () => {
102
- return new webpack.HotModuleReplacementPlugin();
103
- },
104
- ({ name, context }) => {
105
- const params = new URLSearchParams();
106
- params.set('path', options.path);
107
- params.set('name', name || 'webpack');
108
- params.set('hmr', options.hmr ? 'true' : 'false');
109
- params.set('wss', options.wss ? 'true' : 'false');
110
- params.set('reload', options.reload ? 'true' : 'false');
111
- params.set('overlay', options.overlay ? 'true' : 'false');
112
- params.set('progress', options.progress ? 'true' : 'false');
113
- // Auto add hot client to entry.
114
- return new webpack.EntryPlugin(context, `${client}?${params}`, {
115
- // Don't create runtime.
116
- runtime: false
117
- });
118
- }
97
+ new webpack.HotModuleReplacementPlugin(),
98
+ // Auto add hot client to entry.
99
+ new webpack.EntryPlugin(compiler.context, `${client}?${params}`, {
100
+ // Don't create runtime.
101
+ runtime: false
102
+ })
119
103
  ];
120
- for (const compiler of compilers) {
121
- for (const plugin of plugins) {
122
- plugin(compiler).apply(compiler);
123
- }
124
- }
125
104
  if (options.progress) {
126
- const progress = new webpack.ProgressPlugin((percentage, status, ...messages) => {
127
- if (percentage > this.#percentage) {
128
- this.#percentage = percentage;
129
- this.broadcast(this.clients(), 'progress', { status, messages, percentage });
105
+ plugins.push(
106
+ new webpack.ProgressPlugin((percentage, status, ...messages) => {
107
+ if (percentage > context.percentage) {
108
+ context.percentage = percentage;
109
+ this.#broadcast(context.clients, 'progress', { status, messages, percentage });
110
+ }
111
+ })
112
+ );
113
+ }
114
+ for (const plugin of plugins) {
115
+ plugin.apply(compiler);
116
+ }
117
+ }
118
+ #setupWss(contexts) {
119
+ const logger = this.#logger;
120
+ const server = this.#server;
121
+ const { path } = this.#options;
122
+ server.on('connection', (client, { url: input = path }) => {
123
+ const url = new URL(input, BASE_URL);
124
+ const uuid = url.searchParams.get('uuid');
125
+ if (uuid) {
126
+ const context = contexts.get(uuid);
127
+ if (context) {
128
+ const { stats } = context;
129
+ context.clients.add(client);
130
+ logger.log('client connected');
131
+ client.on('close', () => {
132
+ context.clients.delete(client);
133
+ logger.log('client disconnected');
134
+ });
135
+ if (stats) {
136
+ const clients = new Set([client]);
137
+ this.#broadcastStats(clients, stats);
138
+ }
139
+ } else {
140
+ client.close(4001, 'compiler not found');
130
141
  }
131
- });
132
- progress.apply(compiler);
142
+ } else {
143
+ client.close(4000, 'uuid not found');
144
+ }
145
+ });
146
+ server.on('error', error => {
147
+ logger.error(error);
148
+ });
149
+ }
150
+ #broadcast(clients, action, payload) {
151
+ for (const client of clients) {
152
+ if (client.readyState === WebSocket.OPEN) {
153
+ client.send(JSON.stringify({ action, payload }));
154
+ }
133
155
  }
134
156
  }
135
- clients() {
136
- return this.#server.clients;
157
+ #broadcastStats(clients, stats) {
158
+ if (clients.size > 0) {
159
+ const { hash, errors, warnings, builtAt: timestamp } = stats;
160
+ this.#broadcast(clients, 'hash', { hash, timestamp });
161
+ if (hasIssues(errors) || hasIssues(warnings)) {
162
+ this.#broadcast(clients, 'issues', { errors, warnings, timestamp });
163
+ } else {
164
+ this.#broadcast(clients, 'ok', { timestamp });
165
+ }
166
+ }
137
167
  }
138
168
  upgrade(context) {
139
169
  const server = this.#server;
@@ -149,24 +179,6 @@ class Socket {
149
179
  }
150
180
  return false;
151
181
  }
152
- broadcast(clients, action, payload) {
153
- for (const client of clients) {
154
- if (client.readyState === WebSocket.OPEN) {
155
- client.send(JSON.stringify({ action, payload }));
156
- }
157
- }
158
- }
159
- #broadcastStats(clients, stats) {
160
- if (clients.size > 0 || clients.length > 0) {
161
- const { hash, errors, warnings, builtAt: timestamp } = stats;
162
- this.broadcast(clients, 'hash', { hash, timestamp });
163
- if (hasIssues(errors) || hasIssues(warnings)) {
164
- this.broadcast(clients, 'issues', { errors, warnings, timestamp });
165
- } else {
166
- this.broadcast(clients, 'ok', { timestamp });
167
- }
168
- }
169
- }
170
182
  }
171
183
 
172
184
  export { Socket };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @module index
3
+ */
4
+ import { Middleware } from 'koa';
5
+ import { Options } from './interface.js';
6
+ import { UnionCompiler } from '../interface.js';
7
+ export { Options };
8
+ export declare function hot(compiler: UnionCompiler, options?: Options): Middleware;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -14,19 +14,12 @@ import { Socket } from './Socket.js';
14
14
  */
15
15
  function hot(compiler, options) {
16
16
  const socket = new Socket(compiler, options);
17
- const middleware = async (ctx, next) => {
17
+ // Middleware.
18
+ return async (ctx, next) => {
18
19
  if (!socket.upgrade(ctx)) {
19
20
  await next();
20
21
  }
21
22
  };
22
- return Object.assign(middleware, {
23
- clients() {
24
- return socket.clients();
25
- },
26
- broadcast(clients, action, payload) {
27
- socket.broadcast(clients, action, payload);
28
- }
29
- });
30
23
  }
31
24
 
32
25
  export { hot };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @module interface
3
+ */
4
+ import WebSocket from 'ws';
5
+ import webpack from 'webpack';
6
+ import { RequiredKeys } from '../interface.js';
7
+ export interface Options {
8
+ hmr?: boolean;
9
+ path?: string;
10
+ wss?: boolean;
11
+ reload?: boolean;
12
+ overlay?: boolean;
13
+ progress?: boolean;
14
+ }
15
+ export type Clients = Set<WebSocket>;
16
+ export interface CompilerContext {
17
+ percentage: number;
18
+ readonly uuid: string;
19
+ readonly clients: Clients;
20
+ stats: Required<webpack.StatsCompilation> | null;
21
+ }
22
+ export type NormalizedOptions = RequiredKeys<Options, 'hmr' | 'path' | 'reload' | 'overlay' | 'progress'>;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @module utils
3
+ */
4
+ import webpack from 'webpack';
5
+ import { Context } from 'koa';
6
+ import { NormalizedOptions, Options } from './interface.js';
7
+ export declare const BASE_URL = 'wss://127.0.0.1';
8
+ export declare function isUpgradable({ request }: Context): boolean;
9
+ export declare function getOptions(options?: Options): NormalizedOptions;
10
+ export declare function hasIssues<T>(issues: ArrayLike<T> | undefined): boolean;
11
+ export declare function getStatsOptions(compiler: webpack.Compiler): webpack.StatsOptions;
12
+ export declare function getTimestamp({ builtAt, children }: webpack.StatsCompilation): number;
@@ -1,60 +1,44 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
8
8
  */
9
9
 
10
- import { isMultiCompiler, isObject } from '../utils.js';
10
+ import { URL } from 'node:url';
11
+ import { isString, isBoolean } from '../utils.js';
11
12
 
12
13
  /**
13
14
  * @module utils
14
15
  */
16
+ const BASE_URL = 'wss://127.0.0.1';
15
17
  function isUpgradable({ request }) {
16
18
  const upgrade = request.get('Upgrade');
17
19
  return !!upgrade && /^websocket$/i.test(upgrade.trim());
18
20
  }
19
- function normalize(path) {
20
- const segments = [];
21
- const parts = path.split(/[\\/]+/);
22
- for (const segment of parts) {
23
- switch (segment) {
24
- case '.':
25
- break;
26
- case '..':
27
- segments.pop();
28
- break;
29
- default:
30
- segments.push(segment);
31
- break;
32
- }
33
- }
34
- const pathname = segments.join('/');
35
- return pathname.startsWith('/') ? pathname : `/${pathname}`;
36
- }
37
21
  function getOptions(options) {
38
22
  const settings = {
39
23
  hmr: true,
40
- wss: false,
41
24
  path: '/hot',
42
25
  reload: true,
43
26
  overlay: true,
44
27
  progress: true,
45
28
  ...options
46
29
  };
47
- settings.path = normalize(settings.path);
30
+ settings.path = new URL(settings.path, BASE_URL).pathname;
48
31
  return settings;
49
32
  }
50
33
  function hasIssues(issues) {
51
34
  return Array.isArray(issues) && issues.length > 0;
52
35
  }
53
- function normalizeStatsOptions(statsOptions) {
54
- if (!isObject(statsOptions)) {
55
- statsOptions = {
56
- preset: statsOptions
57
- };
36
+ function getStatsOptions(compiler) {
37
+ let statsOptions = compiler.options.stats;
38
+ if (isString(statsOptions)) {
39
+ statsOptions = { preset: statsOptions };
40
+ } else if (isBoolean(statsOptions)) {
41
+ statsOptions = statsOptions ? { preset: 'normal' } : { preset: 'none' };
58
42
  }
59
43
  return {
60
44
  ...statsOptions,
@@ -68,16 +52,6 @@ function normalizeStatsOptions(statsOptions) {
68
52
  errorDetails: false
69
53
  };
70
54
  }
71
- function getStatsOptions(compiler) {
72
- if (isMultiCompiler(compiler)) {
73
- return {
74
- children: compiler.compilers.map(({ options }) => {
75
- return normalizeStatsOptions(options.stats);
76
- })
77
- };
78
- }
79
- return normalizeStatsOptions(compiler.options.stats);
80
- }
81
55
  function getTimestamp({ builtAt, children = [] }) {
82
56
  if (builtAt != null) {
83
57
  return builtAt;
@@ -91,4 +65,4 @@ function getTimestamp({ builtAt, children = [] }) {
91
65
  return timestamp < 0 ? Date.now() : timestamp;
92
66
  }
93
67
 
94
- export { getOptions, getStatsOptions, getTimestamp, hasIssues, isUpgradable };
68
+ export { BASE_URL, getOptions, getStatsOptions, getTimestamp, hasIssues, isUpgradable };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @module index
3
+ */
4
+ import { Middleware } from 'koa';
5
+ import { UnionCompiler } from './interface.js';
6
+ import { Options as HotOptions } from './hot/index.js';
7
+ import { Expose, Options as DevOptions } from './dev/index.js';
8
+ export type Options = DevOptions & {
9
+ hot?: HotOptions | false;
10
+ };
11
+ /**
12
+ * @function server
13
+ * @description Create koa dev server middleware.
14
+ * @param compiler The rspack compiler instance.
15
+ * @param options Options.
16
+ */
17
+ export declare function server(compiler: UnionCompiler, options?: Options): Middleware & Expose;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -17,6 +17,12 @@ import { dev } from './dev/index.js';
17
17
  /**
18
18
  * @module index
19
19
  */
20
+ /**
21
+ * @function server
22
+ * @description Create koa dev server middleware.
23
+ * @param compiler The rspack compiler instance.
24
+ * @param options Options.
25
+ */
20
26
  function server(compiler, options = {}) {
21
27
  validate(schema, options, {
22
28
  name: PLUGIN_NAME,
@@ -34,4 +40,4 @@ function server(compiler, options = {}) {
34
40
  return Object.assign(middleware, devMiddleware, hotMiddleware);
35
41
  }
36
42
 
37
- export { server as default };
43
+ export { server };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @module interface
3
+ */
4
+ import webpack from 'webpack';
5
+ export type UnionStats = webpack.Stats | webpack.MultiStats;
6
+ export type GetProp<T, P extends keyof T> = NonNullable<T[P]>;
7
+ export type StatsOptions = GetProp<webpack.Configuration, 'stats'>;
8
+ export type UnionCompiler = webpack.Compiler | webpack.MultiCompiler;
9
+ export type RequiredKeys<T, K extends keyof T> = T & {
10
+ [P in K]-?: T[P];
11
+ };
12
+ export type Logger = ReturnType<GetProp<webpack.Compiler, 'getInfrastructureLogger'>>;
13
+ export type UnionWatching = webpack.Watching | ReturnType<GetProp<webpack.MultiCompiler, 'watch'>>;
14
+ export type Optional<T extends object, K extends keyof T = keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @module schema
3
+ */
4
+ import { validate } from 'schema-utils';
5
+ type Schema = Parameters<typeof validate>[0];
6
+ export declare const schema: Schema;
7
+ export {};
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @module utils
3
+ */
4
+ import webpack from 'webpack';
5
+ import { UnionCompiler } from './interface.js';
6
+ export declare const PLUGIN_NAME: string;
7
+ export declare function isString(value: unknown): value is string;
8
+ export declare function isBoolean(value: unknown): value is boolean;
9
+ export declare function isFunction(value: unknown): value is Function;
10
+ export declare function getCompilers(compiler: UnionCompiler): webpack.Compiler[];
11
+ export declare function isMultiCompiler(compiler: UnionCompiler): compiler is webpack.MultiCompiler;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @package webpack-dev-service
3
3
  * @license MIT
4
- * @version 0.13.2
4
+ * @version 0.14.0
5
5
  * @author nuintun <nuintun@qq.com>
6
6
  * @description A koa 2 middleware for webpack development and hot reloading.
7
7
  * @see https://github.com/nuintun/webpack-dev-service#readme
@@ -12,9 +12,6 @@
12
12
  */
13
13
  const { toString } = Object.prototype;
14
14
  const PLUGIN_NAME = 'webpack-dev-service';
15
- function isObject(value) {
16
- return toString.call(value) === '[object Object]';
17
- }
18
15
  function isString(value) {
19
16
  return toString.call(value) === '[object String]';
20
17
  }
@@ -34,4 +31,4 @@ function isMultiCompiler(compiler) {
34
31
  return 'compilers' in compiler;
35
32
  }
36
33
 
37
- export { PLUGIN_NAME, getCompilers, isBoolean, isFunction, isMultiCompiler, isObject, isString };
34
+ export { PLUGIN_NAME, getCompilers, isBoolean, isFunction, isMultiCompiler, isString };
package/global.d.ts CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  /// <reference types="webpack/module" />
6
6
 
7
+ declare const __ESM__: boolean;
8
+
7
9
  declare const __HOT_CLIENT__: string;
8
10
 
9
11
  declare const __PLUGIN_NAME__: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webpack-dev-service",
3
- "version": "0.13.2",
3
+ "version": "0.14.0",
4
4
  "description": "A koa 2 middleware for webpack development and hot reloading.",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -76,40 +76,41 @@
76
76
  "dependencies": {
77
77
  "@nuintun/ansi": "^0.1.1",
78
78
  "@types/koa": "^2.15.0",
79
- "@types/ws": "^8.5.12",
79
+ "@types/ws": "^8.5.13",
80
80
  "etag": "^1.8.1",
81
- "memfs": "^4.14.0",
81
+ "memfs": "^4.15.0",
82
82
  "range-parser": "^1.2.1",
83
- "schema-utils": "^4.2.0",
83
+ "schema-utils": "^4.3.0",
84
84
  "supports-color": "^9.4.0",
85
85
  "tslib": "^2.8.1",
86
+ "uuid": "^11.0.3",
86
87
  "ws": "^8.18.0"
87
88
  },
88
89
  "devDependencies": {
89
- "@rollup/plugin-replace": "^6.0.1",
90
- "@rollup/plugin-typescript": "^12.1.1",
91
- "@swc/core": "^1.7.42",
92
- "@swc/helpers": "^0.5.13",
90
+ "@rollup/plugin-replace": "^6.0.2",
91
+ "@rollup/plugin-typescript": "^12.1.2",
92
+ "@swc/core": "^1.10.1",
93
+ "@swc/helpers": "^0.5.15",
93
94
  "@types/etag": "^1.8.3",
94
- "@types/node": "^22.8.6",
95
+ "@types/node": "^22.10.2",
95
96
  "@types/range-parser": "^1.2.7",
96
- "@types/react": "^18.3.12",
97
- "@types/react-dom": "^18.3.1",
97
+ "@types/react": "^19.0.1",
98
+ "@types/react-dom": "^19.0.2",
98
99
  "css-loader": "^7.1.2",
100
+ "dts-paths": "^1.0.0",
99
101
  "html-webpack-plugin": "^5.6.3",
100
102
  "koa": "^2.15.3",
101
103
  "koa-compress": "^5.1.1",
102
- "magic-string": "^0.30.12",
104
+ "magic-string": "^0.30.17",
103
105
  "mini-css-extract-plugin": "^2.9.2",
104
- "prettier": "^3.3.3",
105
- "react": "^18.3.1",
106
- "react-dom": "^18.3.1",
106
+ "prettier": "^3.4.2",
107
+ "react": "^19.0.0",
108
+ "react-dom": "^19.0.0",
107
109
  "rimraf": "^6.0.1",
108
- "rollup": "^4.24.3",
110
+ "rollup": "^4.28.1",
109
111
  "swc-loader": "^0.2.6",
110
- "tsc-alias": "^1.8.10",
111
- "typescript": "^5.6.3",
112
- "webpack": "^5.96.0"
112
+ "typescript": "^5.7.2",
113
+ "webpack": "^5.97.1"
113
114
  },
114
115
  "peerDependencies": {
115
116
  "koa": ">=2.0.0",
@@ -9,5 +9,6 @@ export interface Options {
9
9
  readonly reload: boolean;
10
10
  readonly overlay: boolean;
11
11
  readonly progress: boolean;
12
+ readonly uuid: string | null;
12
13
  }
13
- export default function createClient(options: Options): void;
14
+ export declare function createClient(options: Options): void;
@@ -2,15 +2,8 @@
2
2
  * @module events
3
3
  */
4
4
  import { Options } from './client';
5
- import { GetProp } from '../server/interface';
6
- import { HashMessage, InvalidMessage, IssuesMessage, OkMessage, ProgressMessage } from './Message';
7
- export interface Messages {
8
- ok: GetProp<OkMessage, 'payload'>;
9
- hash: GetProp<HashMessage, 'payload'>;
10
- issues: GetProp<IssuesMessage, 'payload'>;
11
- invalid: GetProp<InvalidMessage, 'payload'>;
12
- progress: GetProp<ProgressMessage, 'payload'>;
13
- }
5
+ import { GetProp } from '/server/interface';
6
+ import { Messages } from '/server/hot/Message';
14
7
  export interface Events {
15
8
  ok(message: GetProp<Messages, 'ok'>, options: Options): void;
16
9
  hash(message: GetProp<Messages, 'hash'>, options: Options): void;