Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"language": "en,en-gb",
"words": [
"apos",
"beforeunload",
"camelcase",
"tapable",
"sockjs",
Expand Down
1 change: 1 addition & 0 deletions client-src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ const overlay =
*/
const reloadApp = ({ hot, liveReload }, currentStatus) => {
if (currentStatus.isUnloading) {
log.warn("HMR blocked. Please refresh the page.");
return;
}

Expand Down
33 changes: 33 additions & 0 deletions examples/client/beforeunload/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Beforeunload Example

**webpack.config.js**

```js
module.exports = {
devServer: {
hot: true,
liveReload: true, // Both HMR and Live Reload can be affected
},
};
```

Usage via CLI:

```console
npx webpack serve --open
```

This example demonstrates an issue where webpack-dev-server's `isUnloading` flag gets stuck after canceling the browser's "Leave site?" dialog, blocking both HMR and Live Reload updates.

## What Should Happen

The script should open `http://localhost:8080/` in your default browser.

1. Click **"Add Beforeunload Event"** button
2. Try to reload the page and click **"Cancel"** in the dialog
3. Edit `app.js` file to trigger rebuild
4. **Issue**: Page updates are blocked until manual refresh

## How to Fix

**Manually refresh the page** (F5/Ctrl+R) to restore HMR and Live Reload functionality.
57 changes: 57 additions & 0 deletions examples/client/beforeunload/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"use strict";

const target = document.querySelector("#target");

function beforeunloadHandler(event) {
event.preventDefault();
event.returnValue = "";
return "";
}

let isEventRegistered = false;

const addEventButton = document.createElement("button");
addEventButton.textContent = "Add Beforeunload Event";
addEventButton.style.cssText =
"padding: 10px 20px; margin: 10px; font-size: 16px; cursor: pointer; background-color: #28a745; color: white; border: none; border-radius: 4px;";
addEventButton.addEventListener("click", function () {
if (!isEventRegistered) {
window.addEventListener("beforeunload", beforeunloadHandler);
isEventRegistered = true;
updateStatus();
console.log("[webpack-dev-server] beforeunload event added");
}
});

const reloadButton = document.createElement("button");
reloadButton.textContent = "Reload Page";
reloadButton.style.cssText =
"padding: 10px 20px; margin: 10px; font-size: 16px; cursor: pointer; background-color: #007bff; color: white; border: none; border-radius: 4px;";
reloadButton.addEventListener("click", function () {
window.location.reload();
});

const statusDisplay = document.createElement("div");
statusDisplay.style.cssText =
"margin: 10px; padding: 10px; border: 2px solid #ccc; border-radius: 4px; font-weight: bold;";

function updateStatus() {
statusDisplay.textContent = isEventRegistered
? "Status: Beforeunload event is ACTIVE - Page exit will be blocked"
: "Status: Beforeunload event is INACTIVE - Page exit will not be blocked";
statusDisplay.style.backgroundColor = isEventRegistered
? "#d4edda"
: "#f8d7da";
statusDisplay.style.borderColor = isEventRegistered ? "#28a745" : "#dc3545";
}

target.classList.add("pass");
target.innerHTML = "Beforeunload Event Controller";
target.appendChild(document.createElement("br"));
target.appendChild(document.createElement("br"));
target.appendChild(statusDisplay);
target.appendChild(document.createElement("br"));
target.appendChild(addEventButton);
target.appendChild(reloadButton);

updateStatus();
14 changes: 14 additions & 0 deletions examples/client/beforeunload/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"use strict";

// our setup function adds behind-the-scenes bits to the config that all of our
// examples need
const { setup } = require("../../util");

module.exports = setup({
context: __dirname,
entry: "./app.js",
devServer: {
hot: true,
liveReload: true,
},
});