Skip to content

Commit

Permalink
Apply HMR updates via node worker thread (#10071)
Browse files Browse the repository at this point in the history
  • Loading branch information
devongovett authored Jan 11, 2025
1 parent e3a2b72 commit ee909d4
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 134 deletions.
15 changes: 7 additions & 8 deletions packages/reporters/dev-server/src/HMRServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,16 @@ export default class HMRServer {
this.broadcast(this.unresolvedError);
}

async emitUpdate(event: {
async getUpdate(event: {
+bundleGraph: BundleGraph<PackagedBundle> | BundleGraph<NamedBundle>,
+changedAssets: Map<string, Asset>,
...
}) {
}): Promise<?HMRMessage> {
this.unresolvedError = null;
this.bundleGraph = event.bundleGraph;

let changedAssets = new Set(event.changedAssets.values());
if (changedAssets.size === 0) return;
if (changedAssets.size === 0) return Promise.resolve(null);

let queue = new PromiseQueue({maxConcurrent: FS_CONCURRENCY});
for (let asset of changedAssets) {
Expand Down Expand Up @@ -227,15 +227,14 @@ export default class HMRServer {
}

let assets = await queue.run();

if (assets.length >= BROADCAST_MAX_ASSETS) {
// Too many assets to send via an update without errors, just reload instead
this.broadcast({type: 'reload'});
} else {
this.broadcast({
return {type: 'reload'};
} else if (assets.length > 0) {
return {
type: 'update',
assets,
});
};
}
}

Expand Down
40 changes: 32 additions & 8 deletions packages/reporters/dev-server/src/NodeRunner.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {md, errorToDiagnostic} from '@parcel/diagnostic';
import nullthrows from 'nullthrows';
import {Worker} from 'worker_threads';
import path from 'path';
import type {HMRMessage} from './HMRServer';

export type NodeRunnerOptions = {|
hmr: boolean,
Expand Down Expand Up @@ -37,7 +38,7 @@ export class NodeRunner {
}
}

startWorker() {
startWorker(): Promise<void> {
let entry = nullthrows(this.bundleGraph)
.getEntryBundles()
.find(b => b.env.isNode() && b.type === 'js');
Expand All @@ -54,12 +55,6 @@ export class NodeRunner {
stderr: true,
});

worker.on('message', msg => {
if (msg === 'restart') {
this.restartWorker();
}
});

worker.on('error', (err: Error) => {
this.logger.error(errorToDiagnostic(err));
});
Expand Down Expand Up @@ -91,6 +86,12 @@ export class NodeRunner {
});

this.worker = worker;

return new Promise(resolve => {
worker.once('online', () => resolve());
});
} else {
return Promise.resolve();
}
}

Expand All @@ -105,7 +106,30 @@ export class NodeRunner {
// HMR updates are sent before packaging is complete.
// If the build is still pending, wait until it completes to restart.
if (!this.pending) {
this.startWorker();
await this.startWorker();
}
}

emitUpdate(update: HMRMessage): Promise<void> {
if (update.type === 'reload') {
return this.restartWorker();
}

return new Promise((resolve, reject) => {
let worker = this.worker;
if (worker) {
worker.once('message', msg => {
if (msg === 'restart') {
this.restartWorker().then(resolve, reject);
} else {
resolve();
}
});

worker.postMessage(update);
} else {
resolve();
}
});
}
}
15 changes: 13 additions & 2 deletions packages/reporters/dev-server/src/ServerReporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,15 @@ export default (new Reporter({
// no stale bundles are served. Otherwise emit it for 'buildSuccess'.
options.serveOptions !== false
) {
await hmrServer.emitUpdate(event);
let update = await hmrServer.getUpdate(event);
if (update) {
// If running in node, wait for the server to update before emitting the update
// on the client. This ensures that when the client reloads the server is ready.
if (nodeRunner) {
await nodeRunner.emitUpdate(update);
}
hmrServer.broadcast(update);
}
}
break;
case 'buildSuccess': {
Expand All @@ -131,7 +139,10 @@ export default (new Reporter({
server.buildSuccess(event.bundleGraph, event.requestBundle);
}
if (hmrServer && options.serveOptions === false) {
await hmrServer.emitUpdate(event);
let update = await hmrServer.getUpdate(event);
if (update) {
hmrServer.broadcast(update);
}
}

if (!nodeRunner && options.serveOptions) {
Expand Down
Loading

0 comments on commit ee909d4

Please sign in to comment.