Start a production server from `sourcecred start` (#247)
Summary: This commit changes `yarn start` to run a production version of the API server, which serves static files from a pre-built directory and also handles API requests. Test Plan: ```shell $ yarn build $ yarn backend $ node ./bin/sourcecred.js start -d /tmp/srccrd & $ mkdir -p /tmp/srccrd $ echo hello >/tmp/srccrd/world $ curl -s localhost:4000/ | file - /dev/stdin: HTML document, ASCII text, with very long lines, with no line terminators $ curl -s localhost:4000/api/v1/data/world hello ``` wchargin-branch: cli-start-prod-server
This commit is contained in:
parent
ac8d0ff66c
commit
cb1339a0a7
|
@ -2,8 +2,14 @@
|
||||||
|
|
||||||
import express from "express";
|
import express from "express";
|
||||||
|
|
||||||
export default function apiApp(sourcecredDirectory: string) {
|
export default function apiApp(
|
||||||
|
sourcecredDirectory: string,
|
||||||
|
staticFiles?: string
|
||||||
|
) {
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use("/api/v1/data", express.static(sourcecredDirectory));
|
app.use("/api/v1/data", express.static(sourcecredDirectory));
|
||||||
|
if (staticFiles != null) {
|
||||||
|
app.use(express.static(staticFiles));
|
||||||
|
}
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
|
|
||||||
import {Command} from "@oclif/command";
|
import {Command} from "@oclif/command";
|
||||||
import chalk from "chalk";
|
import chalk from "chalk";
|
||||||
import child_process from "child_process";
|
import fs from "fs";
|
||||||
import express from "express";
|
|
||||||
import {choosePort} from "react-dev-utils/WebpackDevServerUtils";
|
import {choosePort} from "react-dev-utils/WebpackDevServerUtils";
|
||||||
import tmp from "tmp";
|
|
||||||
|
|
||||||
|
import apiApp from "../../app/apiApp";
|
||||||
import {sourcecredDirectoryFlag} from "../common";
|
import {sourcecredDirectoryFlag} from "../common";
|
||||||
|
|
||||||
// Makes the script crash on unhandled rejections instead of silently
|
// Makes the script crash on unhandled rejections instead of silently
|
||||||
|
@ -35,14 +34,11 @@ export default class StartCommand extends Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function startServer(sourcecredDirectory: string) {
|
async function startServer(sourcecredDirectory: string) {
|
||||||
let server, webpack;
|
let server;
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
if (server && server.listening) {
|
if (server && server.listening) {
|
||||||
server.close();
|
server.close();
|
||||||
}
|
}
|
||||||
if (webpack) {
|
|
||||||
webpack.kill();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let shuttingDown = false;
|
let shuttingDown = false;
|
||||||
|
@ -59,10 +55,13 @@ async function startServer(sourcecredDirectory: string) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const webpackWorkdir = tmp.dirSync({unsafeCleanup: true}).name;
|
const staticFiles = "./build/";
|
||||||
|
if (!fs.existsSync(staticFiles)) {
|
||||||
|
console.error("Build output not found. Did you run `yarn build`?");
|
||||||
|
}
|
||||||
|
|
||||||
console.log(chalk.bold("Starting Express..."));
|
console.log(chalk.bold("Starting Express..."));
|
||||||
const expressApp = createExpressApp(webpackWorkdir, sourcecredDirectory);
|
const expressApp = apiApp(sourcecredDirectory, staticFiles);
|
||||||
server = await new Promise(async (resolve, _unused_reject) => {
|
server = await new Promise(async (resolve, _unused_reject) => {
|
||||||
const port = await choosePort(HOST, DEFAULT_PORT);
|
const port = await choosePort(HOST, DEFAULT_PORT);
|
||||||
let server = expressApp.listen(port, () => {
|
let server = expressApp.listen(port, () => {
|
||||||
|
@ -74,44 +73,7 @@ async function startServer(sourcecredDirectory: string) {
|
||||||
cleanup();
|
cleanup();
|
||||||
});
|
});
|
||||||
console.log(
|
console.log(
|
||||||
chalk.green(`Server listening on port ${server.address().port}. `) +
|
chalk.green(`Server listening on port ${server.address().port}.`)
|
||||||
`You might want to wait for Webpack to say ${chalk.bold("[built]")}.`
|
|
||||||
);
|
);
|
||||||
console.log();
|
console.log();
|
||||||
|
|
||||||
console.log(chalk.bold("Starting Webpack..."));
|
|
||||||
webpack = startWebpack(webpackWorkdir);
|
|
||||||
webpack.on("exit", (code, signal) => {
|
|
||||||
console.log(
|
|
||||||
`${chalk.bold("Webpack exited")} with ${code} (signal: ${signal})`
|
|
||||||
);
|
|
||||||
cleanup();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function createExpressApp(webpackWorkdir, sourcecredDirectory) {
|
|
||||||
const app = express();
|
|
||||||
app.use(express.static(webpackWorkdir));
|
|
||||||
app.use("/__data__", express.static(sourcecredDirectory));
|
|
||||||
return app;
|
|
||||||
}
|
|
||||||
|
|
||||||
function startWebpack(workdir: string) {
|
|
||||||
const webpack = child_process.spawn(
|
|
||||||
"yarn",
|
|
||||||
[
|
|
||||||
"--silent",
|
|
||||||
"webpack",
|
|
||||||
"--config",
|
|
||||||
"./config/webpack.config.dev.js",
|
|
||||||
"--output-path",
|
|
||||||
workdir,
|
|
||||||
"--watch",
|
|
||||||
],
|
|
||||||
{
|
|
||||||
env: {...process.env, NODE_ENV: "development"},
|
|
||||||
stdio: "inherit",
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return webpack;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue