Skip to content

Commit ff97695

Browse files
authored
feat: Add support for refreshing hmr on failure (#182)
* feat: Add support for refreshing hmr on failure * fix: Fix logic * fix: Fix tests * test: Add a test against force refresh feature * fix: Fix logic for refresh on failure It looks like that requires a little different kind of check. * fix: Make client implementation work properly in mixed mode I found a better place for applying the logic. * chore: Add an initial example * fix: Fix client link * chore: Update dependency to avoid a warning * chore: Move the example behind recipes * chore: Add a recipe * chore: Drop React linting Recipes aren't linted anyhow.
1 parent 8f85878 commit ff97695

File tree

17 files changed

+2674
-823
lines changed

17 files changed

+2674
-823
lines changed

.eslintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"extends": "shellscape",
2+
"extends": ["shellscape"],
33
"globals": {
44
"document": true,
55
"ʎɐɹɔosǝʌɹǝs": true,

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,12 @@ This setting can be handy when using the HTML5 History API; `index.html` page wi
131131
_Note: The `Accept` header is explicitly stripped from the `/wps` WebSocket path when using `historyFallback`, due to [an issue](https://github.com/shellscape/webpack-plugin-serve/issues/94) with how Firefox and the middleware interact._
132132

133133
### `hmr`
134-
Type: `boolean`<br>
134+
Type: `boolean | 'refresh-on-failure'`<br>
135135
Default: `true`
136136

137137
If `true`, will enable [`Hot Module Replacement`](https://webpack.js.org/concepts/hot-module-replacement/) which exchanges, adds, or removes modules from a bundle dynamically while the application still running, without the need of a full page reload.
138138

139-
_Note: If the build process generates errors, the client (browser) will not be notified of new changes and no HMR will be performed. Errors must be resolved before HMR can proceed._
139+
_Note: If the build process generates errors, the client (browser) will not be notified of new changes and no HMR will be performed. Errors must be resolved before HMR can proceed. To force a refresh, pass `refresh-on-failure' to this option._
140140

141141
_Note: If using in combination with `http2`, the `http2` option `allowHTTP1` must be enabled for the HMR WS connection to work._
142142

lib/client/client.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111
/* eslint-disable global-require */
1212
const run = (buildHash, options) => {
13-
const { address, client = {}, progress, secure, status } = options;
13+
const { address, client = {}, hmr, progress, secure, status } = options;
1414

1515
options.firstInstance = !window.webpackPluginServe; // eslint-disable-line no-param-reassign
1616

@@ -67,7 +67,7 @@ const run = (buildHash, options) => {
6767
// matches the wpsId set in options. this is how we can identify multiple compilers in the
6868
// client.
6969
if (wpsId && wpsId === options.wpsId) {
70-
replace(buildHash, hash);
70+
replace(buildHash, hash, hmr === 'refresh-on-failure');
7171
}
7272
break;
7373
default:

lib/client/hmr.js

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,25 @@ const { error, info, refresh, warn } = require('./log')();
1212

1313
let latest = true;
1414

15-
const hmr = {
16-
onUnaccepted(data) {
17-
warn('Change in unaccepted module(s):\n', data);
18-
warn(data);
19-
},
20-
onDeclined(data) {
21-
warn('Change in declined module(s):\n', data);
22-
},
23-
onErrored(data) {
24-
error('Error in module(s):\n', data);
25-
}
15+
const hmr = (onFailure) => {
16+
return {
17+
onUnaccepted(data) {
18+
onFailure();
19+
warn('Change in unaccepted module(s):\n', data);
20+
warn(data);
21+
},
22+
onDeclined(data) {
23+
onFailure();
24+
warn('Change in declined module(s):\n', data);
25+
},
26+
onErrored(data) {
27+
onFailure();
28+
error('Error in module(s):\n', data);
29+
}
30+
};
2631
};
2732

28-
const replace = async (buildHash, hash) => {
33+
const replace = async (buildHash, hash, refreshOnFailure) => {
2934
const { apply, check, status } = module.hot;
3035

3136
if (hash) {
@@ -57,7 +62,18 @@ const replace = async (buildHash, hash) => {
5762
return;
5863
}
5964

60-
modules = await apply(hmr);
65+
modules = await apply(
66+
hmr(
67+
refreshOnFailure
68+
? () => {
69+
if (refreshOnFailure) {
70+
// eslint-disable-next-line no-undef
71+
location.reload();
72+
}
73+
}
74+
: () => {}
75+
)
76+
);
6177

6278
if (modules) {
6379
latest = true;

lib/validate.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ module.exports = {
4242
compress: nullable(boolean()),
4343
headers: nullable(type({})),
4444
historyFallback: union([boolean(), type({})]),
45-
hmr: boolean(),
45+
hmr: union([boolean(), literal('refresh-on-failure')]),
4646
host: nullable(union([promise, string()])),
4747
http2: union([boolean(), type({})]),
4848
https: nullable(type({})),

0 commit comments

Comments
 (0)