-
Notifications
You must be signed in to change notification settings - Fork 904
/
runServer.ts
146 lines (131 loc) · 4.19 KB
/
runServer.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import Metro from 'metro';
import type Server from 'metro/src/Server';
import type {Middleware} from 'metro-config';
import {Terminal} from 'metro-core';
import path from 'path';
import {
createDevServerMiddleware,
indexPageMiddleware,
} from '@react-native-community/cli-server-api';
import {Config} from '@react-native-community/cli-types';
import loadMetroConfig from '../../tools/loadMetroConfig';
import {version} from '@react-native-community/cli-tools';
import enableWatchMode from './watchMode';
export type Args = {
assetPlugins?: string[];
cert?: string;
customLogReporterPath?: string;
host?: string;
https?: boolean;
maxWorkers?: number;
key?: string;
platforms?: string[];
port?: number;
resetCache?: boolean;
sourceExts?: string[];
transformer?: string;
watchFolders?: string[];
config?: string;
projectRoot?: string;
interactive: boolean;
};
async function runServer(_argv: Array<string>, ctx: Config, args: Args) {
let reportEvent: ((event: any) => void) | undefined;
const terminal = new Terminal(process.stdout);
const ReporterImpl = getReporterImpl(args.customLogReporterPath);
const terminalReporter = new ReporterImpl(terminal);
const reporter = {
update(event: any) {
terminalReporter.update(event);
if (reportEvent) {
reportEvent(event);
}
},
};
const metroConfig = await loadMetroConfig(ctx, {
config: args.config,
maxWorkers: args.maxWorkers,
port: args.port,
resetCache: args.resetCache,
watchFolders: args.watchFolders,
projectRoot: args.projectRoot,
sourceExts: args.sourceExts,
reporter,
});
if (args.assetPlugins) {
// @ts-ignore - assigning to readonly property
metroConfig.transformer.assetPlugins = args.assetPlugins.map((plugin) =>
require.resolve(plugin),
);
}
const {
middleware,
websocketEndpoints,
messageSocketEndpoint,
eventsSocketEndpoint,
} = createDevServerMiddleware({
host: args.host,
port: metroConfig.server.port,
watchFolders: metroConfig.watchFolders,
});
middleware.use(indexPageMiddleware);
const customEnhanceMiddleware = metroConfig.server.enhanceMiddleware;
// @ts-ignore - assigning to readonly property
metroConfig.server.enhanceMiddleware = (
metroMiddleware: Middleware,
server: Server,
) => {
if (customEnhanceMiddleware) {
metroMiddleware = customEnhanceMiddleware(metroMiddleware, server);
}
return middleware.use(metroMiddleware);
};
const serverInstance = await Metro.runServer(metroConfig, {
host: args.host,
secure: args.https,
secureCert: args.cert,
secureKey: args.key,
// @ts-ignore - ws.Server types are incompatible
websocketEndpoints,
});
reportEvent = eventsSocketEndpoint.reportEvent;
if (args.interactive) {
enableWatchMode(messageSocketEndpoint, ctx);
}
// In Node 8, the default keep-alive for an HTTP connection is 5 seconds. In
// early versions of Node 8, this was implemented in a buggy way which caused
// some HTTP responses (like those containing large JS bundles) to be
// terminated early.
//
// As a workaround, arbitrarily increase the keep-alive from 5 to 30 seconds,
// which should be enough to send even the largest of JS bundles.
//
// For more info: https://github.com/nodejs/node/issues/13391
//
serverInstance.keepAliveTimeout = 30000;
await version.logIfUpdateAvailable(ctx.root);
}
function getReporterImpl(customLogReporterPath: string | undefined) {
if (customLogReporterPath === undefined) {
return require('metro/src/lib/TerminalReporter');
}
try {
// First we let require resolve it, so we can require packages in node_modules
// as expected. eg: require('my-package/reporter');
return require(customLogReporterPath);
} catch (e) {
if ((<any>e).code !== 'MODULE_NOT_FOUND') {
throw e;
}
// If that doesn't work, then we next try relative to the cwd, eg:
// require('./reporter');
return require(path.resolve(customLogReporterPath));
}
}
export default runServer;