Skip to content

Commit

Permalink
Switch HMR connection to register bundle entry points via a message
Browse files Browse the repository at this point in the history
Summary:
This diff builds on the previous ones and changes the setup process from using the WebSocket URL to using a message that is sent after the connection is established. It also exposes a function on the HMRClient that allows registering more bundles, which I will make use of in the next (and hopefully final :D ) diff.

I was initially planning on using structured data, like `{bundleName, platform}` but decided to keep using URLs as that is the format used throughout Metro. In fact, when we parse the options from the URL, we need to re-encode the input URL to create the `sourceMapUrl`. I thought it doesn't make sense to write more code to send structured data over the connection only to re-construct a URL on the server manually.

Finally, I also slightly modified the "Internal Bundler" error that is shown in a RedBox (now used by the websocket connection if an invalid message is received). I removed the "internal" wording from the message and I'm actually attaching the failure message to the error instead of directing users to the Terminal.

Reviewed By: gaearon

Differential Revision: D16162729

fbshipit-source-id: 977fde5f6c2f1c14efb4fd99ed30a6bf95a3b13e
  • Loading branch information
cpojer authored and facebook-github-bot committed Jul 18, 2019
1 parent c8ec2ae commit 93bebf1
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 11 deletions.
44 changes: 33 additions & 11 deletions Libraries/Utilities/HMRClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ import NativeRedBox from '../NativeModules/specs/NativeRedBox';

import type {ExtendedError} from '../Core/Devtools/parseErrorStack';

const pendingEntryPoints = [];
let hmrClient = null;
let hmrUnavailableReason: string | null = null;
let isRegisteringEntryPoints = false;

export type HMRClientNativeInterface = {|
enable(): void,
disable(): void,
registerBundle(requestUrl: string): void,
setup(
platform: string,
bundleEntry: string,
Expand Down Expand Up @@ -70,6 +73,8 @@ const HMRClient: HMRClientNativeInterface = {
// Don't warn about the same modules twice.
hmrClient.outdatedModules.clear();
}

registerBundleEntryPoints(hmrClient);
},

disable() {
Expand All @@ -81,6 +86,12 @@ const HMRClient: HMRClientNativeInterface = {
hmrClient.shouldApplyUpdates = false;
},

registerBundle(requestUrl: string) {
invariant(hmrClient, 'Expected HMRClient.setup() call at startup.');
pendingEntryPoints.push(requestUrl);
registerBundleEntryPoints(hmrClient);
},

// Called once by the bridge on startup, even if Fast Refresh is off.
// It creates the HMR client but doesn't actually set up the socket yet.
setup(
Expand All @@ -99,10 +110,12 @@ const HMRClient: HMRClientNativeInterface = {
const HMRLoadingView = require('./HMRLoadingView');

const wsHost = port !== null && port !== '' ? `${host}:${port}` : host;
const client = new MetroHMRClient(
const client = new MetroHMRClient(`ws://${wsHost}/hot`);
hmrClient = client;

pendingEntryPoints.push(
`ws://${wsHost}/hot?bundleEntry=${bundleEntry}&platform=${platform}`,
);
hmrClient = client;

client.on('connection-error', e => {
let error = `Fast Refresh isn't working because it cannot connect to the development server.
Expand All @@ -129,22 +142,18 @@ Error: ${e.message}`;
setHMRUnavailableReason(error);
});

let didFinishInitialUpdate = false;
client.on('connection-done', () => {
// Don't show the loading view during the initial update.
didFinishInitialUpdate = true;
});

// This is intentionally called lazily, as these values change.
function isFastRefreshActive() {
return (
// Until we get "connection-done", messages aren't real edits.
didFinishInitialUpdate &&
// If HMR is disabled by the user, we're ignoring updates.
client.shouldApplyUpdates
client.shouldApplyUpdates && !isRegisteringEntryPoints
);
}

client.on('bundle-registered', () => {
isRegisteringEntryPoints = false;
});

function dismissRedbox() {
if (
Platform.OS === 'ios' &&
Expand Down Expand Up @@ -257,4 +266,17 @@ function getShortModuleName(fullName) {
return shortName;
}

function registerBundleEntryPoints(client) {
if (pendingEntryPoints.length > 0) {
isRegisteringEntryPoints = true;
client.send(
JSON.stringify({
type: 'register-entrypoints',
entryPoints: pendingEntryPoints,
}),
);
pendingEntryPoints.length = 0;
}
}

module.exports = HMRClient;
1 change: 1 addition & 0 deletions Libraries/Utilities/HMRClientProdShim.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const HMRClientProdShim: HMRClientNativeInterface = {
);
},
disable() {},
registerBundle() {},
};

module.exports = HMRClientProdShim;

0 comments on commit 93bebf1

Please sign in to comment.