Proxy Webpack dev server through to an API server (#245)
Summary: This way, our frontend can talk to a backend that can read from the filesystem (among other things). Paired with @decentralion. Test Plan: ``` $ yarn backend $ SOURCECRED_DIRECTORY=/tmp/srccrd yarn start $ # verify that the browser looks good $ mkdir /tmp/srccrd $ echo hello >/tmp/srccrd/world $ curl localhost:3000/api/v1/data/world hello $ curl localhost:4000/api/v1/data/world hello ``` wchargin-branch: webpack-proxy
This commit is contained in:
parent
62b9f70d00
commit
9ea1f981aa
|
@ -57,6 +57,7 @@ module.exports = {
|
||||||
"commands/graph": resolveApp("src/cli/commands/graph.js"),
|
"commands/graph": resolveApp("src/cli/commands/graph.js"),
|
||||||
"commands/plugin-graph": resolveApp("src/cli/commands/pluginGraph.js"),
|
"commands/plugin-graph": resolveApp("src/cli/commands/pluginGraph.js"),
|
||||||
"commands/start": resolveApp("src/cli/commands/start.js"),
|
"commands/start": resolveApp("src/cli/commands/start.js"),
|
||||||
|
apiApp: resolveApp("src/app/apiApp.js"),
|
||||||
sourcecred: resolveApp("src/cli/sourcecred.js"),
|
sourcecred: resolveApp("src/cli/sourcecred.js"),
|
||||||
fetchAndPrintGithubRepo: resolveApp(
|
fetchAndPrintGithubRepo: resolveApp(
|
||||||
"src/plugins/github/bin/fetchAndPrintGithubRepo.js"
|
"src/plugins/github/bin/fetchAndPrintGithubRepo.js"
|
||||||
|
|
117
scripts/start.js
117
scripts/start.js
|
@ -15,6 +15,8 @@ process.on("unhandledRejection", (err) => {
|
||||||
// Ensure environment variables are read.
|
// Ensure environment variables are read.
|
||||||
require("../config/env");
|
require("../config/env");
|
||||||
|
|
||||||
|
const os = require("os");
|
||||||
|
const path = require("path");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const chalk = require("chalk");
|
const chalk = require("chalk");
|
||||||
const webpack = require("webpack");
|
const webpack = require("webpack");
|
||||||
|
@ -36,13 +38,20 @@ const useYarn = fs.existsSync(paths.yarnLockFile);
|
||||||
const isInteractive =
|
const isInteractive =
|
||||||
typeof process.stdout.isTTY !== "undefined" && process.stdout.isTTY;
|
typeof process.stdout.isTTY !== "undefined" && process.stdout.isTTY;
|
||||||
|
|
||||||
|
// The following module is generated by running `yarn backend`. We want
|
||||||
|
// to be able to run Flow without having generated the module, and its
|
||||||
|
// types aren't very rich, anyway, so we stub out the type of `require`
|
||||||
|
// itself.
|
||||||
|
const apiApp = /*:: ((require: any) => */ require("../bin/apiApp")
|
||||||
|
.default /*:: )() */;
|
||||||
|
|
||||||
// Warn and crash if required files are missing
|
// Warn and crash if required files are missing
|
||||||
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tools like Cloud9 rely on this.
|
const DEFAULT_WEBPACK_PORT = parseInt(process.env.PORT, 10) || 3000;
|
||||||
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
|
const DEFAULT_API_PORT = parseInt(process.env.PORT + 1000, 10) || 4000;
|
||||||
const HOST = process.env.HOST || "0.0.0.0";
|
const HOST = process.env.HOST || "0.0.0.0";
|
||||||
|
|
||||||
if (process.env.HOST) {
|
if (process.env.HOST) {
|
||||||
|
@ -62,48 +71,68 @@ if (process.env.HOST) {
|
||||||
|
|
||||||
// We attempt to use the default port but if it is busy, we offer the user to
|
// We attempt to use the default port but if it is busy, we offer the user to
|
||||||
// run on a different port. `choosePort()` Promise resolves to the next free port.
|
// run on a different port. `choosePort()` Promise resolves to the next free port.
|
||||||
choosePort(HOST, DEFAULT_PORT)
|
async function main() {
|
||||||
.then((port) => {
|
const webpackPort = await choosePort(HOST, DEFAULT_WEBPACK_PORT);
|
||||||
if (port == null) {
|
const apiPort = await choosePort(HOST, DEFAULT_API_PORT);
|
||||||
// We have not found a port.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const protocol = process.env.HTTPS === "true" ? "https" : "http";
|
|
||||||
const appName = "sourcecred";
|
|
||||||
const urls = prepareUrls(protocol, HOST, port);
|
|
||||||
// Create a webpack compiler that is configured with custom messages.
|
|
||||||
const compiler = createCompiler(webpack, config, appName, urls, useYarn);
|
|
||||||
// Load proxy config
|
|
||||||
const proxySetting = undefined;
|
|
||||||
const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
|
|
||||||
// Serve webpack assets generated by the compiler over a web sever.
|
|
||||||
const serverConfig = createDevServerConfig(
|
|
||||||
proxyConfig,
|
|
||||||
urls.lanUrlForConfig
|
|
||||||
);
|
|
||||||
const devServer = new WebpackDevServer(compiler, serverConfig);
|
|
||||||
// Launch WebpackDevServer.
|
|
||||||
devServer.listen(port, HOST, (err) => {
|
|
||||||
if (err) {
|
|
||||||
return console.log(err);
|
|
||||||
}
|
|
||||||
if (isInteractive) {
|
|
||||||
clearConsole();
|
|
||||||
}
|
|
||||||
console.log(chalk.cyan("Starting the development server...\n"));
|
|
||||||
openBrowser(urls.localUrlForBrowser);
|
|
||||||
});
|
|
||||||
|
|
||||||
["SIGINT", "SIGTERM"].forEach(function(sig) {
|
if (webpackPort == null) {
|
||||||
process.on(sig, function() {
|
console.error("Could not find a port for the Webpack server.");
|
||||||
devServer.close();
|
}
|
||||||
process.exit();
|
if (apiPort == null) {
|
||||||
});
|
console.error("Could not find a port for the API server.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourcecredDirectory =
|
||||||
|
process.env.SOURCECRED_DIRECTORY || path.join(os.tmpdir(), "sourcecred");
|
||||||
|
const apiServer = await new Promise(async (resolve, _unused_reject) => {
|
||||||
|
let server = apiApp(sourcecredDirectory).listen(apiPort, () => {
|
||||||
|
resolve(server);
|
||||||
});
|
});
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
if (err && err.message) {
|
|
||||||
console.log(err.message);
|
|
||||||
}
|
|
||||||
process.exit(1);
|
|
||||||
});
|
});
|
||||||
|
console.log(
|
||||||
|
chalk.green(`Server listening on port ${apiServer.address().port}.`)
|
||||||
|
);
|
||||||
|
console.log();
|
||||||
|
|
||||||
|
const protocol = process.env.HTTPS === "true" ? "https" : "http";
|
||||||
|
const appName = "sourcecred";
|
||||||
|
const urls = prepareUrls(protocol, HOST, webpackPort);
|
||||||
|
// Create a webpack compiler that is configured with custom messages.
|
||||||
|
const compiler = createCompiler(webpack, config, appName, urls, useYarn);
|
||||||
|
// Load proxy config
|
||||||
|
const proxySetting = {
|
||||||
|
"/api": {
|
||||||
|
target: `${protocol}://localhost:${apiServer.address().port}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
|
||||||
|
// Serve webpack assets generated by the compiler over a web sever.
|
||||||
|
const serverConfig = createDevServerConfig(proxyConfig, urls.lanUrlForConfig);
|
||||||
|
const devServer = new WebpackDevServer(compiler, serverConfig);
|
||||||
|
// Launch WebpackDevServer.
|
||||||
|
devServer.listen(webpackPort, HOST, (err) => {
|
||||||
|
if (err) {
|
||||||
|
return console.log(err);
|
||||||
|
}
|
||||||
|
if (isInteractive) {
|
||||||
|
clearConsole();
|
||||||
|
}
|
||||||
|
console.log(chalk.cyan("Starting the development server...\n"));
|
||||||
|
openBrowser(urls.localUrlForBrowser);
|
||||||
|
});
|
||||||
|
|
||||||
|
["SIGINT", "SIGTERM"].forEach(function(sig) {
|
||||||
|
process.on(sig, function() {
|
||||||
|
devServer.close();
|
||||||
|
apiServer.close();
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((err) => {
|
||||||
|
if (err && err.message) {
|
||||||
|
console.log(err.message);
|
||||||
|
}
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import express from "express";
|
||||||
|
|
||||||
|
export default function apiApp(sourcecredDirectory: string) {
|
||||||
|
const app = express();
|
||||||
|
app.use("/api/v1/data", express.static(sourcecredDirectory));
|
||||||
|
return app;
|
||||||
|
}
|
Loading…
Reference in New Issue