Miguel Jimenez Esun ad0fe15e2e Move polyfills to react-native
Summary:
React Native bundler (aka Metro Bundler) was splitted from the main codebase some time ago (now it lives [[https://github.com/facebook/metro-bundler|here]]). To make it more agnostic, polyfills will be moved out from it, so people who doesn't need them does not include them. However, RN will still need them, so the first step is to copy them back to RN so that we can provide them to Metro Bundler later.

We also include a way of passing the list of polyfills to include, as an `Array<string>`. The field is called `polyfills`, and defaults to the traditional list that is currently included in the package manager [see here](be1843cddc/packages/metro-bundler/src/defaults.js (L27-L37)).

In future commits, `metro-bundler` will be able to manage the `polyfills` array passed to it, and use it, instead of the pre-defined ones.

Reviewed By: davidaurelio

Differential Revision: D5381614

fbshipit-source-id: 749d536b781843ecb3067803e44398cd6df941f1
2017-07-11 03:47:16 -07:00

176 lines
6.3 KiB
JavaScript

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @flow
* @format
*/
'use strict';
require('../../setupBabel')();
const ReactPackager = require('metro-bundler');
const Terminal = require('metro-bundler/src/lib/Terminal');
const attachHMRServer = require('./util/attachHMRServer');
const connect = require('connect');
const copyToClipBoardMiddleware = require('./middleware/copyToClipBoardMiddleware');
const cpuProfilerMiddleware = require('./middleware/cpuProfilerMiddleware');
const defaultAssetExts = require('metro-bundler/src/defaults').assetExts;
const defaultSourceExts = require('metro-bundler/src/defaults').sourceExts;
const defaultPlatforms = require('metro-bundler/src/defaults').platforms;
const defaultProvidesModuleNodeModules = require('metro-bundler/src/defaults')
.providesModuleNodeModules;
const fs = require('fs');
const getDevToolsMiddleware = require('./middleware/getDevToolsMiddleware');
const http = require('http');
const https = require('https');
const indexPageMiddleware = require('./middleware/indexPage');
const loadRawBodyMiddleware = require('./middleware/loadRawBodyMiddleware');
const messageSocket = require('./util/messageSocket.js');
const openStackFrameInEditorMiddleware = require('./middleware/openStackFrameInEditorMiddleware');
const path = require('path');
const statusPageMiddleware = require('./middleware/statusPageMiddleware.js');
const systraceProfileMiddleware = require('./middleware/systraceProfileMiddleware.js');
const webSocketProxy = require('./util/webSocketProxy.js');
import type {ConfigT} from '../util/Config';
import type {Reporter} from 'metro-bundler/src/lib/reporting';
export type Args = {|
+assetExts: $ReadOnlyArray<string>,
+host: string,
+maxWorkers: number,
+nonPersistent: boolean,
+platforms: $ReadOnlyArray<string>,
+port: number,
+projectRoots: $ReadOnlyArray<string>,
+resetCache: boolean,
+sourceExts: $ReadOnlyArray<string>,
+verbose: boolean,
|};
function runServer(
args: Args,
config: ConfigT,
// FIXME: this is weird design. The top-level should pass down a custom
// reporter rather than passing it up as argument to an event.
startedCallback: (reporter: Reporter) => mixed,
readyCallback: (reporter: Reporter) => mixed,
) {
var wsProxy = null;
var ms = null;
const packagerServer = getPackagerServer(args, config);
startedCallback(packagerServer._reporter);
const app = connect()
.use(loadRawBodyMiddleware)
.use(connect.compress())
.use(
getDevToolsMiddleware(args, () => wsProxy && wsProxy.isChromeConnected()),
)
.use(getDevToolsMiddleware(args, () => ms && ms.isChromeConnected()))
.use(openStackFrameInEditorMiddleware(args))
.use(copyToClipBoardMiddleware)
.use(statusPageMiddleware)
.use(systraceProfileMiddleware)
.use(cpuProfilerMiddleware)
.use(indexPageMiddleware)
.use(packagerServer.processRequest.bind(packagerServer));
args.projectRoots.forEach(root => app.use(connect.static(root)));
app.use(connect.logger()).use(connect.errorHandler());
if (args.https && (!args.key || !args.cert)) {
throw new Error('Cannot use https without specifying key and cert options');
}
const serverInstance = args.https
? https.createServer(
{
key: fs.readFileSync(args.key),
cert: fs.readFileSync(args.cert),
},
app,
)
: http.createServer(app);
serverInstance.listen(args.port, args.host, 511, function() {
attachHMRServer({
httpServer: serverInstance,
path: '/hot',
packagerServer,
});
wsProxy = webSocketProxy.attachToServer(serverInstance, '/debugger-proxy');
ms = messageSocket.attachToServer(serverInstance, '/message');
readyCallback(packagerServer._reporter);
});
// Disable any kind of automatic timeout behavior for incoming
// requests in case it takes the packager more than the default
// timeout of 120 seconds to respond to a request.
serverInstance.timeout = 0;
}
function getPackagerServer(args, config) {
const transformModulePath = args.transformer
? path.resolve(args.transformer)
: typeof config.getTransformModulePath === 'function'
? config.getTransformModulePath()
: undefined;
const providesModuleNodeModules =
args.providesModuleNodeModules || defaultProvidesModuleNodeModules;
let LogReporter;
if (args.customLogReporterPath) {
try {
// First we let require resolve it, so we can require packages in node_modules
// as expected. eg: require('my-package/reporter');
/* $FlowFixMe: can't type dynamic require */
LogReporter = require(args.customLogReporterPath);
} catch (e) {
// If that doesn't work, then we next try relative to the cwd, eg:
// require('./reporter');
/* $FlowFixMe: can't type dynamic require */
LogReporter = require(path.resolve(args.customLogReporterPath));
}
} else {
LogReporter = require('metro-bundler/src/lib/TerminalReporter');
}
/* $FlowFixMe: Flow is wrong, Node.js docs specify that process.stdout is an
* instance of a net.Socket (a local socket, not network). */
const terminal = new Terminal(process.stdout);
return ReactPackager.createServer({
assetExts: defaultAssetExts.concat(args.assetExts),
blacklistRE: config.getBlacklistRE(),
cacheVersion: '3',
extraNodeModules: config.extraNodeModules,
getTransformOptions: config.getTransformOptions,
hasteImpl: config.hasteImpl,
maxWorkers: args.maxWorkers,
platforms: defaultPlatforms.concat(args.platforms),
polyfillModuleNames: config.getPolyfillModuleNames(),
polyfills: config.polyfills,
postMinifyProcess: config.postMinifyProcess,
postProcessModules: config.postProcessModules,
projectRoots: args.projectRoots,
providesModuleNodeModules: providesModuleNodeModules,
reporter: new LogReporter(terminal),
resetCache: args.resetCache,
sourceExts: defaultSourceExts.concat(args.sourceExts),
transformModulePath: transformModulePath,
verbose: args.verbose,
watch: !args.nonPersistent,
workerPath: config.getWorkerPath(),
});
}
module.exports = runServer;