Make flipper-server stand-alone servable

Summary:
This diff makes flipper-server stand-alone servable as a single package.

It basically works as follows:

- (default) plugins are build as usually into static folder
- static folder is copied into flipper-server/static (as far as relevant)
- `flipper-server/src/index.tsx` is bundled into `flipper-server/dist/index.js`
- `flipper-ui-browser/src/index.tsx` is bundled into `flipper-server/static/bundle.js`

If flipper-server is started without the `--bundler` config, the `bundle.js` will be served statically, rather than starting up the Metro bundler with all the typical transforms (in a distributed version of the package those all wouldn't resolve)

Things to be done in next diffs:

* make sure plugins actually load in the non bundled setup
* make sure flipper-server gets published properly
* make sure build is created as part of CI

At the end of this stack, running `npx flipper-server` on any machine should basically be a viable approach to get flipper up and running locally :)

Reviewed By: nikoant

Differential Revision: D33171107

fbshipit-source-id: 4af8ac2699467a0b55283fe084640482700744c2
This commit is contained in:
Michel Weststrate
2021-12-24 02:15:25 -08:00
committed by Facebook GitHub Bot
parent d48fbd8e50
commit 6ff4abbc67
13 changed files with 515 additions and 84 deletions

View File

@@ -8,19 +8,22 @@
*/
const dotenv = require('dotenv').config();
import child from 'child_process';
import chalk from 'chalk';
import path from 'path';
import {compileServerMain, prepareDefaultPlugins} from './build-utils';
import {
compileServerMain,
launchServer,
prepareDefaultPlugins,
} from './build-utils';
import Watchman from './watchman';
import {serverDir} from './paths';
import {serverStaticDir} from './paths';
import isFB from './isFB';
import yargs from 'yargs';
import open from 'open';
import ensurePluginFoldersWatchable from './ensurePluginFoldersWatchable';
import {remove} from 'fs-extra';
const argv = yargs
.usage('yarn start [args]')
.usage('yarn flipper-server [args]')
.options({
'default-plugins': {
describe:
@@ -57,11 +60,6 @@ const argv = yargs
'[FB-internal only] Will force using public sources only, to be able to iterate quickly on the public version. If sources are checked out from GitHub this is already the default. Setting env var "FLIPPER_FORCE_PUBLIC_BUILD" is equivalent.',
type: 'boolean',
},
build: {
describe:
'Build the server without watching for changing or starting the service',
type: 'boolean',
},
open: {
describe: 'Open Flipper in the default browser after starting',
type: 'boolean',
@@ -122,31 +120,12 @@ if (argv['enabled-plugins'] !== undefined) {
process.env.FLIPPER_ENABLED_PLUGINS = argv['enabled-plugins'].join(',');
}
let proc: child.ChildProcess | undefined;
function launchServer() {
console.log('⚙️ Launching flipper-server...');
proc = child.spawn(
'node',
['--inspect=9229', `../flipper-server/server.js`],
{
cwd: serverDir,
env: {
...process.env,
},
stdio: 'inherit',
},
);
}
let startCount = 0;
async function restartServer() {
if (proc) {
proc.kill(9);
await sleep(1000);
}
try {
await compileServerMain();
await launchServer();
await compileServerMain(true);
await launchServer(true, ++startCount === 1); // only openon the first time
} catch (e) {
console.error(
chalk.red(
@@ -193,6 +172,8 @@ async function startWatchChanges() {
}
(async () => {
await remove(serverStaticDir);
if (dotenv && dotenv.parsed) {
console.log('✅ Loaded env vars from .env file: ', dotenv.parsed);
}
@@ -200,24 +181,9 @@ async function startWatchChanges() {
process.env.FLIPPER_RELEASE_CHANNEL === 'insiders',
);
// build?
if (argv['build']) {
await compileServerMain();
} else {
// watch
await startWatchChanges();
await ensurePluginFoldersWatchable();
// builds and starts
await restartServer();
if (argv.open) {
await sleep(2000);
// TODO: make port configurable together with flipper-server
open('http://localhost:52342/index.web.dev.html');
}
}
// watch
await startWatchChanges();
await ensurePluginFoldersWatchable();
// builds and starts
await restartServer();
})();
function sleep(ms: number) {
return new Promise((r) => setTimeout(r, ms));
}