Skip to content

Commit

Permalink
Make the React Native HMR client extend from the generic metro HMR cl…
Browse files Browse the repository at this point in the history
…ient

Reviewed By: BYK

Differential Revision: D6752278

fbshipit-source-id: 5c93cba3e9f3cee2119cb90a711909e0b4a5b835
  • Loading branch information
rafeca authored and facebook-github-bot committed Jan 22, 2018
1 parent b8e79a7 commit 9a19867
Showing 1 changed file with 46 additions and 81 deletions.
127 changes: 46 additions & 81 deletions Libraries/Utilities/HMRClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule HMRClient
* @format
* @flow
*/
'use strict';

const Platform = require('Platform');
const invariant = require('fbjs/lib/invariant');

const MetroHMRClient = require('metro/src/lib/bundle-modules/HMRClient');

This comment has been minimized.

Copy link
@SandroMachado

SandroMachado Jan 25, 2018

Contributor

I think this change broke the build from the source. I am getting this error:

Loading dependency graph, done.
warning: the transform cache was reset.
error: bundling failed: Error: Unable to resolve module `metro/src/lib/bundle-modules/HMRClient` from `/Users/<userdirectory>/Desktop/temp/react-native/Libraries/Utilities/HMRClient.js`: Module does not exist in the module map

This comment has been minimized.

Copy link
@chirag04

chirag04 Jan 25, 2018

Contributor

This comment has been minimized.

Copy link
@janicduplessis

janicduplessis Jan 26, 2018

Contributor

The file is actually named HmrClient.js when downloaded from npm but is named HMRClient.js in the metro repo (https://github.com/facebook/metro/blob/master/packages/metro/src/lib/bundle-modules/HMRClient.js)

This comment has been minimized.

Copy link
@hramos

hramos Feb 6, 2018

Contributor

metro 0.25.0 has fixed the HmrClient.js filename issue.

The build is still breaking on this line, though. I'm investigating.


/**
* HMR Client that receives from the server HMR updates and propagates them
* runtime to reflects those changes.
Expand All @@ -24,110 +27,72 @@ const HMRClient = {
invariant(bundleEntry, 'Missing required paramenter `bundleEntry`');
invariant(host, 'Missing required paramenter `host`');

// need to require WebSocket inside of `enable` function because
// this module is defined as a `polyfillGlobal`.
// See `InitializeJavascriptAppEngine.js`
const WebSocket = require('WebSocket');
// Moving to top gives errors due to NativeModules not being initialized
const HMRLoadingView = require('HMRLoadingView');

const wsHostPort = port !== null && port !== ''
? `${host}:${port}`
: host;
const wsHostPort = port !== null && port !== '' ? `${host}:${port}` : host;

bundleEntry = bundleEntry.replace(/\.(bundle|delta)/, '.js');

// Build the websocket url
const wsUrl = `ws://${wsHostPort}/hot?` +
const wsUrl =
`ws://${wsHostPort}/hot?` +
`platform=${platform}&` +
`bundleEntry=${bundleEntry}`;

const activeWS = new WebSocket(wsUrl);
activeWS.onerror = (e) => {
let error = (
`Hot loading isn't working because it cannot connect to the development server.
const hmrClient = new MetroHMRClient(wsUrl);

hmrClient.on('connection-error', e => {
let error = `Hot loading isn't working because it cannot connect to the development server.
Try the following to fix the issue:
- Ensure that the packager server is running and available on the same network`
);
- Ensure that the packager server is running and available on the same network`;

if (Platform.OS === 'ios') {
error += (
`
- Ensure that the Packager server URL is correctly set in AppDelegate`
);
error += `
- Ensure that the Packager server URL is correctly set in AppDelegate`;
} else {
error += (
`
error += `
- Ensure that your device/emulator is connected to your machine and has USB debugging enabled - run 'adb devices' to see a list of connected devices
- If you're on a physical device connected to the same machine, run 'adb reverse tcp:8081 tcp:8081' to forward requests from your device
- If your device is on the same Wi-Fi network, set 'Debug server host & port for device' in 'Dev settings' to your machine's IP address and the port of the local dev server - e.g. 10.0.1.1:8081`
);
- If your device is on the same Wi-Fi network, set 'Debug server host & port for device' in 'Dev settings' to your machine's IP address and the port of the local dev server - e.g. 10.0.1.1:8081`;
}

error += (
`
error += `
URL: ${host}:${port}
Error: ${e.message}`
);
Error: ${e.message}`;

throw new Error(error);
};
activeWS.onmessage = ({data}) => {
// Moving to top gives errors due to NativeModules not being initialized
const HMRLoadingView = require('HMRLoadingView');

data = JSON.parse(data);

switch (data.type) {
case 'update-start': {
HMRLoadingView.showMessage('Hot Loading...');
break;
}
case 'update': {
const {
modules,
sourceMappingURLs,
sourceURLs,
} = data.body;

if (Platform.OS === 'ios') {
const RCTRedBox = require('NativeModules').RedBox;
RCTRedBox && RCTRedBox.dismiss && RCTRedBox.dismiss();
} else {
const RCTExceptionsManager = require('NativeModules').ExceptionsManager;
RCTExceptionsManager && RCTExceptionsManager.dismissRedbox && RCTExceptionsManager.dismissRedbox();
}

modules.forEach(({id, code}, i) => {
code = code + '\n\n' + sourceMappingURLs[i];

// on JSC we need to inject from native for sourcemaps to work
// (Safari doesn't support `sourceMappingURL` nor any variant when
// evaluating code) but on Chrome we can simply use eval
const injectFunction = typeof global.nativeInjectHMRUpdate === 'function'
? global.nativeInjectHMRUpdate
: eval; // eslint-disable-line no-eval

injectFunction(code, sourceURLs[i]);
});

HMRLoadingView.hide();
break;
}
case 'update-done': {
HMRLoadingView.hide();
break;
}
case 'error': {
HMRLoadingView.hide();
throw new Error(`${data.body.type}: ${data.body.message}`);
}
default: {
throw new Error(`Unexpected message: ${data}`);
}
});

hmrClient.on('update-start', () => {
HMRLoadingView.showMessage('Hot Loading...');
});

hmrClient.on('update', () => {
if (Platform.OS === 'ios') {
const RCTRedBox = require('NativeModules').RedBox;
RCTRedBox && RCTRedBox.dismiss && RCTRedBox.dismiss();
} else {
const RCTExceptionsManager = require('NativeModules').ExceptionsManager;
RCTExceptionsManager &&
RCTExceptionsManager.dismissRedbox &&
RCTExceptionsManager.dismissRedbox();
}
};
});

hmrClient.on('update-done', () => {
HMRLoadingView.hide();
});

hmrClient.on('error', data => {
HMRLoadingView.hide();
throw new Error(`${data.type} ${data.message}`);
});

hmrClient.enable();
},
};

Expand Down

0 comments on commit 9a19867

Please sign in to comment.