[now dev] Add support for proxying to builder-specific dev servers (#4089)

This is an extension to the Runtime API, where a runtime can optionally define a `startDevServer()` function which is responsible for spawning a single-serve dev server for an individual HTTP request (the dev server is booted up upon receiving an HTTP request, and gets shut down by `now dev` after the HTTP request is completed). For runtimes that define this function, the `build()` function will never be executed, which avoids a lot of unnecessary processing for a dev environment.

Some things this accomplishes:

 * Retains the proper stack trace for errors.
 * Ensures that if a source code file is changed, and then an HTTP request is sent, it's guaranteed to be using the latest code (no file watching, or re-compilations).
 * Avoids creating a Lambda zip file (just to immediately unpack it for dev).
 * Avoids `@zeit/fun` completely, which loses some "correctness" (i.e. function is not frozen in between requests).
 * Backwards compatible with older Now CLIs - versions that don't know about `startDevServer()` will just invoke `build()`, and there's no version change required in the Runtime.
This commit is contained in:
Nathan Rajlich
2020-04-17 13:55:44 -07:00
committed by GitHub
parent a03b8689e9
commit 6fd1b50924
15 changed files with 274 additions and 134 deletions

View File

@@ -0,0 +1,54 @@
import http from 'http';
import path from 'path';
import { createServerWithHelpers } from './helpers';
function listen(
server: http.Server,
port: number,
host: string
): Promise<void> {
return new Promise(resolve => {
server.listen(port, host, () => {
resolve();
});
});
}
async function main() {
const entrypoint = process.env.NOW_DEV_ENTRYPOINT;
if (!entrypoint) {
throw new Error('`NOW_DEV_ENTRYPOINT` must be defined');
}
//const shouldAddHelpers = true;
const entrypointPath = path.join(process.cwd(), entrypoint);
const handler = await import(entrypointPath);
/*
const server = http.createServer((req, res) => {
Promise.resolve(true).then(() => handler.default(req, res)).catch(err => {
console.error('Caught error from HTTP handler:', err);
if (!res.headersSent) {
res.statusCode = 500;
res.end('Internal server error\n');
}
});
});
*/
const server = createServerWithHelpers(handler.default);
await listen(server, 0, '127.0.0.1');
const address = server.address();
if (typeof process.send === 'function') {
process.send(address);
} else {
console.log('Dev server listening:', address);
}
}
main().catch(err => {
console.error(err);
process.exit(1);
});