@modern-js/server 1.5.0 → 1.6.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # @modern-js/server
2
2
 
3
+ ## 1.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 83660b6: chore(server): merge `@modern-js/hmr-client` to `@modern-js/server`
8
+
9
+ chore(server): 合并 `@modern-js/hmr-client` 到 `@modern-js/server`
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [1421965]
14
+ - Updated dependencies [02647d2]
15
+ - Updated dependencies [4fc801f]
16
+ - Updated dependencies [9d60891]
17
+ - Updated dependencies [2ed8f7d]
18
+ - Updated dependencies [e4b73b2]
19
+ - Updated dependencies [c8614b8]
20
+ - Updated dependencies [df73691]
21
+ - @modern-js/webpack@1.12.2
22
+ - @modern-js/utils@1.8.0
23
+ - @modern-js/prod-server@1.2.1
24
+ - @modern-js/server-utils@1.2.11
25
+
26
+ ## 1.5.1
27
+
28
+ ### Patch Changes
29
+
30
+ - a27ab8d: feat: add onApiChange hook for bff hot reload
31
+ feat: 为 BFF 热更新优化,添加 onApiChange 钩子
32
+ - Updated dependencies [b74b0b6]
33
+ - Updated dependencies [7b902b3]
34
+ - Updated dependencies [3d64b2f]
35
+ - Updated dependencies [8b2aa56]
36
+ - Updated dependencies [3e4a34f]
37
+ - Updated dependencies [33cebd2]
38
+ - @modern-js/webpack@1.12.0
39
+ - @modern-js/prod-server@1.2.0
40
+ - @modern-js/server-utils@1.2.11
41
+ - @modern-js/utils@1.7.12
42
+
3
43
  ## 1.5.0
4
44
 
5
45
  ### Minor Changes
@@ -18,7 +18,7 @@ export default class DevServerPlugin {
18
18
  const host = client.host ? `&host=${client.host}` : '';
19
19
  const path = client.path ? `&path=${client.path}` : '';
20
20
  const port = client.port ? `&port=${client.port}` : '';
21
- const clientEntry = `${require.resolve('@modern-js/hmr-client')}?${host}${path}${port}`; // use a hook to add entries if available
21
+ const clientEntry = `${require.resolve("../hmr-client")}?${host}${path}${port}`; // use a hook to add entries if available
22
22
 
23
23
  new EntryPlugin(compiler.context, clientEntry, {
24
24
  name: undefined
@@ -59,18 +59,18 @@ export default class Watcher {
59
59
  watcher.on('change', changed => {
60
60
  if (!fs.existsSync(changed) || cache.isDiff(changed)) {
61
61
  cache.refresh(changed);
62
- callback(changed);
62
+ callback(changed, 'change');
63
63
  }
64
64
  });
65
65
  watcher.on('add', changed => {
66
66
  if (!cache.has(changed)) {
67
67
  cache.add([changed]);
68
- callback(changed);
68
+ callback(changed, 'add');
69
69
  }
70
70
  });
71
71
  watcher.on('unlink', changed => {
72
72
  cache.del(changed);
73
- callback(changed);
73
+ callback(changed, 'unlink');
74
74
  });
75
75
  this.watcher = watcher;
76
76
  }
@@ -0,0 +1,49 @@
1
+ import { HMR_SOCK_PATH } from '@modern-js/utils/constants';
2
+ export function createSocketUrl(resourceQuery) {
3
+ // ?host=localhost&port=8080&path=modern_js_hmr_ws
4
+ const searchParams = resourceQuery.substr(1).split('&');
5
+ const options = {};
6
+
7
+ for (const pair of searchParams) {
8
+ const ary = pair.split('=');
9
+ options[ary[0]] = decodeURIComponent(ary[1]);
10
+ }
11
+
12
+ const currentLocation = self.location;
13
+ return getSocketUrl(options, currentLocation);
14
+ }
15
+ export function formatURL({
16
+ port,
17
+ protocol,
18
+ hostname,
19
+ pathname
20
+ }) {
21
+ if (window.URL) {
22
+ // eslint-disable-next-line node/prefer-global/url, node/no-unsupported-features/node-builtins
23
+ const url = new URL('http://localhost');
24
+ url.port = port;
25
+ url.hostname = hostname;
26
+ url.protocol = protocol;
27
+ url.pathname = pathname;
28
+ return url.toString();
29
+ } // compatible with IE11
30
+
31
+
32
+ const colon = protocol.indexOf(':') === -1 ? ':' : '';
33
+ return `${protocol}${colon}//${hostname}:${port}${pathname}`;
34
+ }
35
+
36
+ function getSocketUrl(urlParts, location) {
37
+ const {
38
+ host,
39
+ port,
40
+ path,
41
+ protocol
42
+ } = urlParts;
43
+ return formatURL({
44
+ protocol: protocol || location.protocol === 'https:' ? 'wss' : 'ws',
45
+ hostname: host || location.hostname,
46
+ port: port || location.port,
47
+ pathname: path || HMR_SOCK_PATH
48
+ });
49
+ }
@@ -0,0 +1,201 @@
1
+ /**
2
+ * This has been adapted from `create-react-app`, authored by Facebook, Inc.
3
+ * see: https://github.com/facebookincubator/create-react-app/tree/master/packages/react-dev-utils
4
+ *
5
+ * Tips: this package will be bundled and running in the browser, do not import from the entry of @modern-js/utils.
6
+ */
7
+ import stripAnsi from '@modern-js/utils/strip-ansi';
8
+ import { formatWebpackMessages } from '@modern-js/utils/format';
9
+ import { createSocketUrl } from "./createSocketUrl"; // declare any to fix the type of `module.hot`
10
+
11
+ // We need to keep track of if there has been a runtime error.
12
+ // Essentially, we cannot guarantee application state was not corrupted by the
13
+ // runtime error. To prevent confusing behavior, we forcibly reload the entire
14
+ // application. This is handled below when we are notified of a compile (code
15
+ // change).
16
+ // See https://github.com/facebook/create-react-app/issues/3096
17
+ const hadRuntimeError = false; // Connect to Dev Server
18
+
19
+ const socketUrl = createSocketUrl(__resourceQuery);
20
+ const connection = new WebSocket(socketUrl); // Unlike WebpackDevServer client, we won't try to reconnect
21
+ // to avoid spamming the console. Disconnect usually happens
22
+ // when developer stops the server.
23
+
24
+ connection.onclose = function () {
25
+ if (typeof console !== 'undefined' && typeof console.info === 'function') {
26
+ console.info('The development server has disconnected.\nRefresh the page if necessary.');
27
+ }
28
+ }; // Remember some state related to hot module replacement.
29
+
30
+
31
+ let isFirstCompilation = true;
32
+ let mostRecentCompilationHash = null;
33
+ let hasCompileErrors = false;
34
+
35
+ function clearOutdatedErrors() {
36
+ // Clean up outdated compile errors, if any.
37
+ // eslint-disable-next-line node/no-unsupported-features/node-builtins, no-console
38
+ if (typeof console !== 'undefined' && typeof console.clear === 'function') {
39
+ if (hasCompileErrors) {
40
+ // eslint-disable-next-line node/no-unsupported-features/node-builtins, no-console
41
+ console.clear();
42
+ }
43
+ }
44
+ } // Successful compilation.
45
+
46
+
47
+ function handleSuccess() {
48
+ clearOutdatedErrors();
49
+ const isHotUpdate = !isFirstCompilation;
50
+ isFirstCompilation = false;
51
+ hasCompileErrors = false; // Attempt to apply hot updates or reload.
52
+
53
+ if (isHotUpdate) {
54
+ tryApplyUpdates();
55
+ }
56
+ } // Compilation with warnings (e.g. ESLint).
57
+
58
+
59
+ function handleWarnings(warnings) {
60
+ clearOutdatedErrors();
61
+ const isHotUpdate = !isFirstCompilation;
62
+ isFirstCompilation = false;
63
+ hasCompileErrors = false;
64
+
65
+ function printWarnings() {
66
+ // Print warnings to the console.
67
+ const formatted = formatWebpackMessages({
68
+ warnings,
69
+ errors: []
70
+ });
71
+
72
+ if (typeof console !== 'undefined' && typeof console.warn === 'function') {
73
+ for (let i = 0; i < formatted.warnings.length; i++) {
74
+ if (i === 5) {
75
+ console.warn('There were more warnings in other files.\n' + 'You can find a complete log in the terminal.');
76
+ break;
77
+ }
78
+
79
+ console.warn(stripAnsi(formatted.warnings[i]));
80
+ }
81
+ }
82
+ }
83
+
84
+ printWarnings(); // Attempt to apply hot updates or reload.
85
+
86
+ if (isHotUpdate) {
87
+ tryApplyUpdates();
88
+ }
89
+ } // Compilation with errors (e.g. syntax error or missing modules).
90
+
91
+
92
+ function handleErrors(errors) {
93
+ clearOutdatedErrors();
94
+ isFirstCompilation = false;
95
+ hasCompileErrors = true; // "Massage" webpack messages.
96
+
97
+ const formatted = formatWebpackMessages({
98
+ errors,
99
+ warnings: []
100
+ }); // Also log them to the console.
101
+
102
+ if (typeof console !== 'undefined' && typeof console.error === 'function') {
103
+ for (const error of formatted.errors) {
104
+ console.error(stripAnsi(error));
105
+ }
106
+ } // Do not attempt to reload now.
107
+ // We will reload on next success instead.
108
+
109
+ } // There is a newer version of the code available.
110
+
111
+
112
+ function handleAvailableHash(hash) {
113
+ // Update last known compilation hash.
114
+ mostRecentCompilationHash = hash;
115
+ } // Handle messages from the server.
116
+
117
+
118
+ connection.onmessage = function (e) {
119
+ const message = JSON.parse(e.data);
120
+
121
+ switch (message.type) {
122
+ case 'hash':
123
+ handleAvailableHash(message.data);
124
+ break;
125
+
126
+ case 'still-ok':
127
+ case 'ok':
128
+ handleSuccess();
129
+ break;
130
+
131
+ case 'content-changed':
132
+ // Triggered when a file from `contentBase` changed.
133
+ window.location.reload();
134
+ break;
135
+
136
+ case 'warnings':
137
+ handleWarnings(message.data);
138
+ break;
139
+
140
+ case 'errors':
141
+ handleErrors(message.data);
142
+ break;
143
+
144
+ default: // Do nothing.
145
+
146
+ }
147
+ }; // Is there a newer version of this code available?
148
+
149
+
150
+ function isUpdateAvailable() {
151
+ // __webpack_hash__ is the hash of the current compilation.
152
+ // It's a global variable injected by webpack.
153
+ return mostRecentCompilationHash !== __webpack_hash__;
154
+ } // webpack disallows updates in other states.
155
+
156
+
157
+ function canApplyUpdates() {
158
+ return module.hot.status() === 'idle';
159
+ } // Attempt to update code on the fly, fall back to a hard reload.
160
+
161
+
162
+ function tryApplyUpdates() {
163
+ if (!module.hot) {
164
+ // HotModuleReplacementPlugin is not in webpack configuration.
165
+ window.location.reload();
166
+ return;
167
+ }
168
+
169
+ if (!isUpdateAvailable() || !canApplyUpdates()) {
170
+ return;
171
+ }
172
+
173
+ function handleApplyUpdates(err, updatedModules) {
174
+ // NOTE: This var is injected by Webpack's DefinePlugin, and is a boolean instead of string.
175
+ const hasReactRefresh = process.env.FAST_REFRESH;
176
+ const wantsForcedReload = err || !updatedModules || hadRuntimeError; // React refresh can handle hot-reloading over errors.
177
+
178
+ if (!hasReactRefresh && wantsForcedReload) {
179
+ window.location.reload();
180
+ return;
181
+ }
182
+
183
+ if (isUpdateAvailable()) {
184
+ // While we were updating, there was a new update! Do it again.
185
+ tryApplyUpdates();
186
+ }
187
+ } // https://webpack.github.io/docs/hot-module-replacement.html#check
188
+
189
+
190
+ const result = module.hot.check(
191
+ /* autoApply */
192
+ true, handleApplyUpdates); // // webpack 2 returns a Promise instead of invoking a callback
193
+
194
+ if (result !== null && result !== void 0 && result.then) {
195
+ result.then(updatedModules => {
196
+ handleApplyUpdates(null, updatedModules);
197
+ }, err => {
198
+ handleApplyUpdates(err, null);
199
+ });
200
+ }
201
+ }
@@ -195,7 +195,8 @@ export class ModernDevServer extends ModernServer {
195
195
  }
196
196
 
197
197
  onServerChange({
198
- filepath
198
+ filepath,
199
+ event
199
200
  }) {
200
201
  const {
201
202
  pwd
@@ -212,9 +213,19 @@ export class ModernDevServer extends ModernServer {
212
213
  });
213
214
  } else {
214
215
  try {
215
- super.onServerChange({
216
- filepath
217
- });
216
+ const success = this.runner.onApiChange([{
217
+ filename: filepath,
218
+ event
219
+ }]); // onApiChange 钩子被调用,且返回 true,则表示无需重新编译
220
+ // onApiChange 的类型是 WaterFall,WaterFall 钩子的返回值类型目前有问题
221
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
222
+ // @ts-expect-error
223
+
224
+ if (success !== true) {
225
+ super.onServerChange({
226
+ filepath
227
+ });
228
+ }
218
229
  } catch (e) {
219
230
  this.logger.error(e);
220
231
  }
@@ -354,11 +365,12 @@ export class ModernDevServer extends ModernServer {
354
365
  const watcher = new Watcher();
355
366
  watcher.createDepTree(); // 监听文件变动,如果有变动则给 client,也就是 start 启动的插件发消息
356
367
 
357
- watcher.listen(defaultWatchedPaths, watchOptions, filepath => {
368
+ watcher.listen(defaultWatchedPaths, watchOptions, (filepath, event) => {
358
369
  watcher.updateDepTree();
359
370
  watcher.cleanDepCache(filepath);
360
371
  this.onServerChange({
361
- filepath
372
+ filepath,
373
+ event
362
374
  });
363
375
  });
364
376
  this.watcher = watcher;
@@ -27,7 +27,7 @@ class DevServerPlugin {
27
27
  const host = client.host ? `&host=${client.host}` : '';
28
28
  const path = client.path ? `&path=${client.path}` : '';
29
29
  const port = client.port ? `&port=${client.port}` : '';
30
- const clientEntry = `${require.resolve('@modern-js/hmr-client')}?${host}${path}${port}`; // use a hook to add entries if available
30
+ const clientEntry = `${require.resolve("../hmr-client")}?${host}${path}${port}`; // use a hook to add entries if available
31
31
 
32
32
  new EntryPlugin(compiler.context, clientEntry, {
33
33
  name: undefined
@@ -82,18 +82,18 @@ class Watcher {
82
82
  watcher.on('change', changed => {
83
83
  if (!_utils.fs.existsSync(changed) || cache.isDiff(changed)) {
84
84
  cache.refresh(changed);
85
- callback(changed);
85
+ callback(changed, 'change');
86
86
  }
87
87
  });
88
88
  watcher.on('add', changed => {
89
89
  if (!cache.has(changed)) {
90
90
  cache.add([changed]);
91
- callback(changed);
91
+ callback(changed, 'add');
92
92
  }
93
93
  });
94
94
  watcher.on('unlink', changed => {
95
95
  cache.del(changed);
96
- callback(changed);
96
+ callback(changed, 'unlink');
97
97
  });
98
98
  this.watcher = watcher;
99
99
  }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createSocketUrl = createSocketUrl;
7
+ exports.formatURL = formatURL;
8
+
9
+ var _constants = require("@modern-js/utils/constants");
10
+
11
+ function createSocketUrl(resourceQuery) {
12
+ // ?host=localhost&port=8080&path=modern_js_hmr_ws
13
+ const searchParams = resourceQuery.substr(1).split('&');
14
+ const options = {};
15
+
16
+ for (const pair of searchParams) {
17
+ const ary = pair.split('=');
18
+ options[ary[0]] = decodeURIComponent(ary[1]);
19
+ }
20
+
21
+ const currentLocation = self.location;
22
+ return getSocketUrl(options, currentLocation);
23
+ }
24
+
25
+ function formatURL({
26
+ port,
27
+ protocol,
28
+ hostname,
29
+ pathname
30
+ }) {
31
+ if (window.URL) {
32
+ // eslint-disable-next-line node/prefer-global/url, node/no-unsupported-features/node-builtins
33
+ const url = new URL('http://localhost');
34
+ url.port = port;
35
+ url.hostname = hostname;
36
+ url.protocol = protocol;
37
+ url.pathname = pathname;
38
+ return url.toString();
39
+ } // compatible with IE11
40
+
41
+
42
+ const colon = protocol.indexOf(':') === -1 ? ':' : '';
43
+ return `${protocol}${colon}//${hostname}:${port}${pathname}`;
44
+ }
45
+
46
+ function getSocketUrl(urlParts, location) {
47
+ const {
48
+ host,
49
+ port,
50
+ path,
51
+ protocol
52
+ } = urlParts;
53
+ return formatURL({
54
+ protocol: protocol || location.protocol === 'https:' ? 'wss' : 'ws',
55
+ hostname: host || location.hostname,
56
+ port: port || location.port,
57
+ pathname: path || _constants.HMR_SOCK_PATH
58
+ });
59
+ }
@@ -0,0 +1,207 @@
1
+ "use strict";
2
+
3
+ var _stripAnsi = _interopRequireDefault(require("@modern-js/utils/strip-ansi"));
4
+
5
+ var _format = require("@modern-js/utils/format");
6
+
7
+ var _createSocketUrl = require("./createSocketUrl");
8
+
9
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
+
11
+ /**
12
+ * This has been adapted from `create-react-app`, authored by Facebook, Inc.
13
+ * see: https://github.com/facebookincubator/create-react-app/tree/master/packages/react-dev-utils
14
+ *
15
+ * Tips: this package will be bundled and running in the browser, do not import from the entry of @modern-js/utils.
16
+ */
17
+ // We need to keep track of if there has been a runtime error.
18
+ // Essentially, we cannot guarantee application state was not corrupted by the
19
+ // runtime error. To prevent confusing behavior, we forcibly reload the entire
20
+ // application. This is handled below when we are notified of a compile (code
21
+ // change).
22
+ // See https://github.com/facebook/create-react-app/issues/3096
23
+ const hadRuntimeError = false; // Connect to Dev Server
24
+
25
+ const socketUrl = (0, _createSocketUrl.createSocketUrl)(__resourceQuery);
26
+ const connection = new WebSocket(socketUrl); // Unlike WebpackDevServer client, we won't try to reconnect
27
+ // to avoid spamming the console. Disconnect usually happens
28
+ // when developer stops the server.
29
+
30
+ connection.onclose = function () {
31
+ if (typeof console !== 'undefined' && typeof console.info === 'function') {
32
+ console.info('The development server has disconnected.\nRefresh the page if necessary.');
33
+ }
34
+ }; // Remember some state related to hot module replacement.
35
+
36
+
37
+ let isFirstCompilation = true;
38
+ let mostRecentCompilationHash = null;
39
+ let hasCompileErrors = false;
40
+
41
+ function clearOutdatedErrors() {
42
+ // Clean up outdated compile errors, if any.
43
+ // eslint-disable-next-line node/no-unsupported-features/node-builtins, no-console
44
+ if (typeof console !== 'undefined' && typeof console.clear === 'function') {
45
+ if (hasCompileErrors) {
46
+ // eslint-disable-next-line node/no-unsupported-features/node-builtins, no-console
47
+ console.clear();
48
+ }
49
+ }
50
+ } // Successful compilation.
51
+
52
+
53
+ function handleSuccess() {
54
+ clearOutdatedErrors();
55
+ const isHotUpdate = !isFirstCompilation;
56
+ isFirstCompilation = false;
57
+ hasCompileErrors = false; // Attempt to apply hot updates or reload.
58
+
59
+ if (isHotUpdate) {
60
+ tryApplyUpdates();
61
+ }
62
+ } // Compilation with warnings (e.g. ESLint).
63
+
64
+
65
+ function handleWarnings(warnings) {
66
+ clearOutdatedErrors();
67
+ const isHotUpdate = !isFirstCompilation;
68
+ isFirstCompilation = false;
69
+ hasCompileErrors = false;
70
+
71
+ function printWarnings() {
72
+ // Print warnings to the console.
73
+ const formatted = (0, _format.formatWebpackMessages)({
74
+ warnings,
75
+ errors: []
76
+ });
77
+
78
+ if (typeof console !== 'undefined' && typeof console.warn === 'function') {
79
+ for (let i = 0; i < formatted.warnings.length; i++) {
80
+ if (i === 5) {
81
+ console.warn('There were more warnings in other files.\n' + 'You can find a complete log in the terminal.');
82
+ break;
83
+ }
84
+
85
+ console.warn((0, _stripAnsi.default)(formatted.warnings[i]));
86
+ }
87
+ }
88
+ }
89
+
90
+ printWarnings(); // Attempt to apply hot updates or reload.
91
+
92
+ if (isHotUpdate) {
93
+ tryApplyUpdates();
94
+ }
95
+ } // Compilation with errors (e.g. syntax error or missing modules).
96
+
97
+
98
+ function handleErrors(errors) {
99
+ clearOutdatedErrors();
100
+ isFirstCompilation = false;
101
+ hasCompileErrors = true; // "Massage" webpack messages.
102
+
103
+ const formatted = (0, _format.formatWebpackMessages)({
104
+ errors,
105
+ warnings: []
106
+ }); // Also log them to the console.
107
+
108
+ if (typeof console !== 'undefined' && typeof console.error === 'function') {
109
+ for (const error of formatted.errors) {
110
+ console.error((0, _stripAnsi.default)(error));
111
+ }
112
+ } // Do not attempt to reload now.
113
+ // We will reload on next success instead.
114
+
115
+ } // There is a newer version of the code available.
116
+
117
+
118
+ function handleAvailableHash(hash) {
119
+ // Update last known compilation hash.
120
+ mostRecentCompilationHash = hash;
121
+ } // Handle messages from the server.
122
+
123
+
124
+ connection.onmessage = function (e) {
125
+ const message = JSON.parse(e.data);
126
+
127
+ switch (message.type) {
128
+ case 'hash':
129
+ handleAvailableHash(message.data);
130
+ break;
131
+
132
+ case 'still-ok':
133
+ case 'ok':
134
+ handleSuccess();
135
+ break;
136
+
137
+ case 'content-changed':
138
+ // Triggered when a file from `contentBase` changed.
139
+ window.location.reload();
140
+ break;
141
+
142
+ case 'warnings':
143
+ handleWarnings(message.data);
144
+ break;
145
+
146
+ case 'errors':
147
+ handleErrors(message.data);
148
+ break;
149
+
150
+ default: // Do nothing.
151
+
152
+ }
153
+ }; // Is there a newer version of this code available?
154
+
155
+
156
+ function isUpdateAvailable() {
157
+ // __webpack_hash__ is the hash of the current compilation.
158
+ // It's a global variable injected by webpack.
159
+ return mostRecentCompilationHash !== __webpack_hash__;
160
+ } // webpack disallows updates in other states.
161
+
162
+
163
+ function canApplyUpdates() {
164
+ return module.hot.status() === 'idle';
165
+ } // Attempt to update code on the fly, fall back to a hard reload.
166
+
167
+
168
+ function tryApplyUpdates() {
169
+ if (!module.hot) {
170
+ // HotModuleReplacementPlugin is not in webpack configuration.
171
+ window.location.reload();
172
+ return;
173
+ }
174
+
175
+ if (!isUpdateAvailable() || !canApplyUpdates()) {
176
+ return;
177
+ }
178
+
179
+ function handleApplyUpdates(err, updatedModules) {
180
+ // NOTE: This var is injected by Webpack's DefinePlugin, and is a boolean instead of string.
181
+ const hasReactRefresh = process.env.FAST_REFRESH;
182
+ const wantsForcedReload = err || !updatedModules || hadRuntimeError; // React refresh can handle hot-reloading over errors.
183
+
184
+ if (!hasReactRefresh && wantsForcedReload) {
185
+ window.location.reload();
186
+ return;
187
+ }
188
+
189
+ if (isUpdateAvailable()) {
190
+ // While we were updating, there was a new update! Do it again.
191
+ tryApplyUpdates();
192
+ }
193
+ } // https://webpack.github.io/docs/hot-module-replacement.html#check
194
+
195
+
196
+ const result = module.hot.check(
197
+ /* autoApply */
198
+ true, handleApplyUpdates); // // webpack 2 returns a Promise instead of invoking a callback
199
+
200
+ if (result !== null && result !== void 0 && result.then) {
201
+ result.then(updatedModules => {
202
+ handleApplyUpdates(null, updatedModules);
203
+ }, err => {
204
+ handleApplyUpdates(err, null);
205
+ });
206
+ }
207
+ }
@@ -220,7 +220,8 @@ class ModernDevServer extends _prodServer.ModernServer {
220
220
  }
221
221
 
222
222
  onServerChange({
223
- filepath
223
+ filepath,
224
+ event
224
225
  }) {
225
226
  const {
226
227
  pwd
@@ -239,9 +240,19 @@ class ModernDevServer extends _prodServer.ModernServer {
239
240
  });
240
241
  } else {
241
242
  try {
242
- super.onServerChange({
243
- filepath
244
- });
243
+ const success = this.runner.onApiChange([{
244
+ filename: filepath,
245
+ event
246
+ }]); // onApiChange 钩子被调用,且返回 true,则表示无需重新编译
247
+ // onApiChange 的类型是 WaterFall,WaterFall 钩子的返回值类型目前有问题
248
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
249
+ // @ts-expect-error
250
+
251
+ if (success !== true) {
252
+ super.onServerChange({
253
+ filepath
254
+ });
255
+ }
245
256
  } catch (e) {
246
257
  this.logger.error(e);
247
258
  }
@@ -381,11 +392,12 @@ class ModernDevServer extends _prodServer.ModernServer {
381
392
  const watcher = new _watcher.default();
382
393
  watcher.createDepTree(); // 监听文件变动,如果有变动则给 client,也就是 start 启动的插件发消息
383
394
 
384
- watcher.listen(defaultWatchedPaths, watchOptions, filepath => {
395
+ watcher.listen(defaultWatchedPaths, watchOptions, (filepath, event) => {
385
396
  watcher.updateDepTree();
386
397
  watcher.cleanDepCache(filepath);
387
398
  this.onServerChange({
388
- filepath
399
+ filepath,
400
+ event
389
401
  });
390
402
  });
391
403
  this.watcher = watcher;
@@ -1,4 +1,5 @@
1
1
  import { FSWatcher, WatchOptions } from '@modern-js/utils';
2
+ export declare type WatchEvent = 'add' | 'change' | 'unlink';
2
3
  export declare const defaultWatchOptions: {
3
4
  ignoreInitial: boolean;
4
5
  ignored: RegExp;
@@ -24,7 +25,7 @@ export declare const mergeWatchOptions: (options?: WatchOptions) => {
24
25
  export default class Watcher {
25
26
  private dependencyTree;
26
27
  private watcher;
27
- listen(files: string[], options: WatchOptions, callback: (changed: string) => void): void;
28
+ listen(files: string[], options: WatchOptions, callback: (changed: string, event: WatchEvent) => void): void;
28
29
  createDepTree(): void;
29
30
  updateDepTree(): void;
30
31
  cleanDepCache(filepath: string): void;
@@ -0,0 +1,12 @@
1
+ export declare function createSocketUrl(resourceQuery: string): string;
2
+ export declare function formatURL({
3
+ port,
4
+ protocol,
5
+ hostname,
6
+ pathname
7
+ }: {
8
+ port: string;
9
+ protocol: string;
10
+ hostname: string;
11
+ pathname: string;
12
+ }): string;
@@ -0,0 +1 @@
1
+ export {};
@@ -2,6 +2,7 @@
2
2
  /// <reference types="node" />
3
3
  import http, { Server, IncomingMessage, ServerResponse } from 'http';
4
4
  import { ServerHookRunner, ModernServer, BuildOptions } from '@modern-js/prod-server';
5
+ import { WatchEvent } from '../dev-tools/watcher';
5
6
  import { ModernDevServerOptions } from '../types';
6
7
  export declare class ModernDevServer extends ModernServer {
7
8
  private mockHandler;
@@ -19,9 +20,11 @@ export declare class ModernDevServer extends ModernServer {
19
20
  createHTTPServer(handler: (req: IncomingMessage, res: ServerResponse, next?: () => void) => void): Promise<http.Server | import("https").Server>;
20
21
  protected warmupSSRBundle(): void;
21
22
  protected onServerChange({
22
- filepath
23
+ filepath,
24
+ event
23
25
  }: {
24
26
  filepath: string;
27
+ event: WatchEvent;
25
28
  }): void;
26
29
  private setupCompiler;
27
30
  private setupDevServerPlugin;
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "modern",
12
12
  "modern.js"
13
13
  ],
14
- "version": "1.5.0",
14
+ "version": "1.6.0",
15
15
  "jsnext:source": "./src/index.ts",
16
16
  "types": "./dist/types/index.d.ts",
17
17
  "main": "./dist/js/node/index.js",
@@ -30,20 +30,19 @@
30
30
  "dependencies": {
31
31
  "@babel/core": "^7.18.0",
32
32
  "@babel/register": "^7.17.7",
33
- "@modern-js/hmr-client": "^1.2.8",
34
- "@modern-js/prod-server": "^1.1.9",
33
+ "@modern-js/prod-server": "^1.2.1",
35
34
  "@modern-js/server-utils": "^1.2.11",
36
- "@modern-js/webpack": "^1.11.3",
37
- "@modern-js/utils": "^1.7.9",
35
+ "@modern-js/webpack": "^1.12.2",
36
+ "@modern-js/utils": "^1.8.0",
38
37
  "devcert": "^1.2.2",
39
38
  "minimatch": "^3.0.4",
40
39
  "path-to-regexp": "^6.2.0",
41
40
  "ws": "^8.2.0"
42
41
  },
43
42
  "devDependencies": {
44
- "@modern-js/core": "1.12.2",
45
- "@modern-js/server-core": "1.4.0",
46
- "@modern-js/types": "1.5.5",
43
+ "@modern-js/core": "1.13.1",
44
+ "@modern-js/server-core": "1.4.1",
45
+ "@modern-js/types": "1.6.0",
47
46
  "@scripts/build": "0.0.0",
48
47
  "@scripts/jest-config": "0.0.0",
49
48
  "@types/jest": "^27",
@@ -52,7 +51,8 @@
52
51
  "@types/ws": "^7.4.7",
53
52
  "jest": "^27",
54
53
  "typescript": "^4",
55
- "websocket": "^1"
54
+ "websocket": "^1",
55
+ "webpack": "^5.71.0"
56
56
  },
57
57
  "sideEffects": false,
58
58
  "modernConfig": {