-
-
Notifications
You must be signed in to change notification settings - Fork 380
feat(client): post build events to the page, and guard reloads #2425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "webpack-dev-middleware": minor | ||
| --- | ||
|
|
||
| Post build events to the page the way webpack-dev-server's client does — `webpackInvalid`, `webpackProgress`, `webpackOk`, `webpackStillOk`, `webpackWarnings`, `webpackErrors`, `webpackClose` and `webpackHotUpdate<hash>` — so a plugin or a framework's dev tooling can follow a build without reaching into the client |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "webpack-dev-middleware": patch | ||
| --- | ||
|
|
||
| Do not reload a page that is already navigating away, and reload the nearest ancestor that has a url of its own when the app runs in an `about:blank` iframe |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "webpack-dev-middleware": patch | ||
| --- | ||
|
|
||
| Give an `overlay.runtimeErrors` filter the rejected value through `error.cause`, so a rejection carrying a plain object rather than an `Error` can still be judged on what it carries |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,95 @@ | ||
| // Set while the page is on its way out, so an update that lands mid-navigation | ||
| // does not reload the page the browser is already leaving. A `beforeunload` can | ||
| // be cancelled — by another listener, or by the user answering "stay" — so the | ||
| // flag is released again shortly after, and `pagehide`/`pageshow` settle the | ||
| // cases `beforeunload` gets wrong (a page kept in the back/forward cache runs | ||
| // the same script again when it comes back). | ||
| const UNLOAD_GRACE_PERIOD = 1000; | ||
|
|
||
| let unloading = false; | ||
| // A reload asked for while the page looked like it was leaving. Held rather | ||
| // than dropped: if the navigation was cancelled the page is staying and still | ||
| // wants the update, and nothing would ask again until the next rebuild. | ||
| let deferred = false; | ||
| /** @type {ReturnType<typeof setTimeout> | undefined} */ | ||
| let graceTimer; | ||
|
|
||
| /** | ||
| * @returns {boolean} whether the page is on its way out | ||
| */ | ||
| export function isUnloading() { | ||
| return unloading; | ||
| } | ||
|
|
||
| /** | ||
| * Reload the page. While it looks like the page is leaving, the reload is held | ||
| * until that turns out to be wrong rather than performed or thrown away. | ||
| * Isolated so tests can stub it — `window.location` is not configurable in | ||
| * modern jsdom. | ||
| */ | ||
| export default function reloadPage() { | ||
| window.location.reload(); | ||
| if (unloading) { | ||
| deferred = true; | ||
|
|
||
| return; | ||
| } | ||
|
alexander-akait marked this conversation as resolved.
|
||
|
|
||
| // In an iframe with no navigable url of its own — `srcdoc`, or a document | ||
| // written into it — reloading would reload `about:blank` and lose the app, so | ||
| // the nearest ancestor that has somewhere to go back to is reloaded instead. | ||
| /** @type {Window} */ | ||
| let target = window; | ||
|
|
||
| try { | ||
| while ( | ||
| target.location.protocol === "about:" && | ||
| target.parent && | ||
| target.parent !== target | ||
| ) { | ||
| target = target.parent; | ||
| } | ||
| } catch { | ||
| // A cross-origin ancestor: its location cannot be read, let alone | ||
| // reloaded. Reloading this frame is the most that is permitted here. | ||
| target = window; | ||
| } | ||
|
|
||
| target.location.reload(); | ||
| } | ||
|
|
||
| if (typeof window !== "undefined" && window.addEventListener) { | ||
| window.addEventListener("beforeunload", () => { | ||
| unloading = true; | ||
|
|
||
| clearTimeout(graceTimer); | ||
|
|
||
| graceTimer = setTimeout(() => { | ||
| unloading = false; | ||
|
|
||
| if (deferred) { | ||
| deferred = false; | ||
| reloadPage(); | ||
| } | ||
| }, UNLOAD_GRACE_PERIOD); | ||
| }); | ||
|
|
||
| // The page really is going now, so stop reloading it for good — and drop | ||
| // anything held, or it would fire into a document on its way out. | ||
| window.addEventListener("pagehide", () => { | ||
| clearTimeout(graceTimer); | ||
|
|
||
| unloading = true; | ||
| deferred = false; | ||
| }); | ||
|
|
||
| // Restored from the back/forward cache: the same script keeps running, so a | ||
| // flag left set by the navigation away would block every later update. The | ||
| // page is showing its own state again, so a reload held from before that | ||
| // navigation is stale and goes no further. | ||
| window.addEventListener("pageshow", () => { | ||
| clearTimeout(graceTimer); | ||
|
|
||
| unloading = false; | ||
| deferred = false; | ||
| }); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| /* global WorkerGlobalScope */ | ||
|
|
||
| // eslint-disable-next-line jsdoc/reject-any-type | ||
| /** @typedef {any} EXPECTED_ANY */ | ||
|
|
||
| /** | ||
| * Whether there is a page to talk to at all. A worker has none — and | ||
| * `WorkerGlobalScope` is not declared where there is no worker, hence the | ||
| * `typeof` guard on it. | ||
| * @returns {boolean} true when `postMessage` reaches a page | ||
| */ | ||
| function canPost() { | ||
| return ( | ||
| typeof self !== "undefined" && | ||
| (typeof WorkerGlobalScope === "undefined" || | ||
| !(self instanceof WorkerGlobalScope)) | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * Announce what the client just handled to whoever else is on the page, so a | ||
| * plugin or a framework's dev tooling can follow a build without reaching into | ||
| * this module. The `webpack` prefix and the payloads match what | ||
| * webpack-dev-server's client has always posted, because the consumers of | ||
| * these messages are the same ones. | ||
| * @param {string} type message type, without the `webpack` prefix | ||
| * @param {EXPECTED_ANY=} data payload | ||
| */ | ||
| export default function sendMessage(type, data) { | ||
| if (!canPost()) { | ||
| return; | ||
| } | ||
|
|
||
| self.postMessage({ type: `webpack${type}`, data }, "*"); | ||
| } | ||
|
|
||
| /** | ||
| * Post a message exactly as given, for the one webpack-dev-server sends as a | ||
| * bare string rather than in the `{ type, data }` shape. | ||
| * @param {EXPECTED_ANY} message the message to post | ||
| */ | ||
| sendMessage.raw = (message) => { | ||
| if (!canPost()) { | ||
| return; | ||
| } | ||
|
|
||
| self.postMessage(message, "*"); | ||
| }; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.