Track plugin changes and notify frontend

Summary: Watch source plugin folders and notify frontend that any of them changed. In subsequent diffs, we will start reloading plugins that changed.

Reviewed By: lblasa

Differential Revision: D39539443

fbshipit-source-id: 726916c0bce336a2c0179558526bcb1b74e35b93
This commit is contained in:
Andrey Goncharov
2022-09-15 10:02:19 -07:00
committed by Facebook GitHub Bot
parent 3639feef61
commit c69d102ca1
10 changed files with 61 additions and 30 deletions

View File

@@ -15,6 +15,7 @@ import fs from 'fs-extra';
import {WebSocketServer} from 'ws';
import pFilter from 'p-filter';
import {homedir} from 'os';
import {InstalledPluginDetails} from 'flipper-common';
// This file is heavily inspired by scripts/start-dev-server.ts!
// part of that is done by start-flipper-server-dev (compiling "main"),
@@ -24,6 +25,8 @@ const uiSourceDirs = [
'flipper-ui-browser',
'flipper-ui-core',
'flipper-plugin-core',
'flipper-plugin',
'flipper-frontend-core',
'flipper-common',
];
@@ -65,7 +68,8 @@ export async function attachDevServer(
// prevent bundling!
const Metro = electronRequire('metro');
const MetroResolver = electronRequire('metro-resolver');
const {getWatchFolders} = electronRequire('flipper-pkg-lib');
const {getWatchFolders, startWatchPlugins} =
electronRequire('flipper-pkg-lib');
const babelTransformationsDir = path.resolve(
rootDir,
@@ -90,7 +94,6 @@ export async function attachDevServer(
uiSourceDirs.map((dir) => getWatchFolders(path.resolve(rootDir, dir))),
)
).flat(),
...(await getPluginSourceFolders()),
]);
const baseConfig = await Metro.loadConfig();
@@ -154,6 +157,17 @@ export async function attachDevServer(
next();
});
await startWatchPlugins((changedPlugins: InstalledPluginDetails[]) => {
socket.clients.forEach((client) => {
client.send(
JSON.stringify({
event: 'plugins-source-updated',
payload: changedPlugins,
}),
);
});
});
console.log('DEV webserver started.');
}

View File

@@ -9,7 +9,10 @@
"license": "MIT",
"bugs": "https://github.com/facebook/flipper/issues",
"dependencies": {
"chalk": "^4",
"esbuild": "^0.15.7",
"fb-watchman": "^2.0.1",
"flipper-common": "0.0.0",
"flipper-plugin-lib": "0.0.0",
"fs-extra": "^10.1.0",
"metro": "^0.70.2",

View File

@@ -11,3 +11,5 @@ export {default as runBuild} from './runBuild';
export {default as getWatchFolders} from './getWatchFolders';
export {default as computePackageChecksum} from './computePackageChecksum';
export {default as stripSourceMapComment} from './stripSourceMap';
export {default as startWatchPlugins} from './startWatchPlugins';
export {default as Watchman} from './watchman';

View File

@@ -8,13 +8,34 @@
*/
import Watchman from './watchman';
import {getPluginSourceFolders, isPluginDir} from 'flipper-plugin-lib';
import {
getInstalledPluginDetails,
getPluginSourceFolders,
isPluginDir,
} from 'flipper-plugin-lib';
import path from 'path';
import chalk from 'chalk';
import {rebuildPlugin} from './build-utils';
import runBuild from './runBuild';
import {InstalledPluginDetails} from 'flipper-common';
async function rebuildPlugin(pluginPath: string) {
try {
await runBuild(pluginPath, true);
console.info(chalk.green('Rebuilt plugin'), pluginPath);
} catch (e) {
console.error(
chalk.red(
'Failed to compile a plugin, waiting for additional changes...',
),
e,
);
}
}
export default async function startWatchPlugins(
onChanged?: () => void | Promise<void>,
onChanged?: (
changedPlugins: InstalledPluginDetails[],
) => void | Promise<void>,
) {
// eslint-disable-next-line no-console
console.log('🕵️‍ Watching for plugin changes');
@@ -27,7 +48,7 @@ export default async function startWatchPlugins(
delayedCompilation = undefined;
// eslint-disable-next-line no-console
console.log(`🕵️‍ Detected plugin change`);
await Promise.all(
const changedDirs = await Promise.all(
// https://facebook.github.io/watchman/docs/nodejs.html#subscribing-to-changes
files.map(async (file: string) => {
const filePathAbs = path.resolve(root, file);
@@ -48,9 +69,15 @@ export default async function startWatchPlugins(
dirPath = path.resolve(dirPath, '..');
}
await rebuildPlugin(dirPath);
return dirPath;
}),
);
onChanged?.();
const changedPlugins = await Promise.all(
changedDirs
.filter((dirPath): dirPath is string => !!dirPath)
.map((dirPath) => getInstalledPluginDetails(dirPath)),
);
onChanged?.(changedPlugins);
}, kCompilationDelayMillis);
}
};

View File

@@ -8,7 +8,7 @@
*/
import {Client} from 'fb-watchman';
import {v4 as uuid} from 'uuid';
import {uuid} from 'flipper-common';
import path from 'path';
const watchmanTimeout = 60 * 1000;

View File

@@ -9,6 +9,9 @@
{
"path": "../babel-transformer"
},
{
"path": "../flipper-common"
},
{
"path": "../plugin-lib"
}

View File

@@ -511,17 +511,3 @@ function defaultResolve(...rest: any[]) {
...rest,
);
}
export async function rebuildPlugin(pluginPath: string) {
try {
await runBuild(pluginPath, true);
console.info(chalk.green('Rebuilt plugin'), pluginPath);
} catch (e) {
console.error(
chalk.red(
'Failed to compile a plugin, waiting for additional changes...',
),
e,
);
}
}

View File

@@ -21,7 +21,6 @@
"dotenv": "^14.2.0",
"electron-builder": "23.0.3",
"express": "^4.17.3",
"fb-watchman": "^2.0.1",
"flipper-common": "0.0.0",
"flipper-pkg-lib": "0.0.0",
"flipper-plugin-lib": "0.0.0",

View File

@@ -21,7 +21,6 @@ import path from 'path';
import fs from 'fs-extra';
import {hostname} from 'os';
import {compileMain, prepareDefaultPlugins} from './build-utils';
import Watchman from './watchman';
// @ts-ignore no typings for metro
import Metro from 'metro';
import {staticDir, babelTransformationsDir, rootDir} from './paths';
@@ -29,8 +28,8 @@ import isFB from './isFB';
import getAppWatchFolders from './get-app-watch-folders';
import {getPluginSourceFolders} from 'flipper-plugin-lib';
import ensurePluginFoldersWatchable from './ensurePluginFoldersWatchable';
import startWatchPlugins from './startWatchPlugins';
import yargs from 'yargs';
import {startWatchPlugins, Watchman} from 'flipper-pkg-lib';
const argv = yargs
.usage('yarn start [args]')
@@ -445,8 +444,8 @@ function checkDevServer() {
await startMetroServer(app, server);
outputScreen(socket);
await compileMain();
await startWatchPlugins(() => {
socket.emit('refresh');
await startWatchPlugins((changedPlugins) => {
socket.emit('plugins-source-updated', changedPlugins);
});
if (dotenv && dotenv.parsed) {
console.log('✅ Loaded env vars from .env file: ', dotenv.parsed);

View File

@@ -15,11 +15,10 @@ import {
launchServer,
prepareDefaultPlugins,
} from './build-utils';
import Watchman from './watchman';
import isFB from './isFB';
import yargs from 'yargs';
import ensurePluginFoldersWatchable from './ensurePluginFoldersWatchable';
import startWatchPlugins from './startWatchPlugins';
import {Watchman} from 'flipper-pkg-lib';
const argv = yargs
.usage('yarn flipper-server [args]')
@@ -195,5 +194,4 @@ async function startWatchChanges() {
await restartServer();
// watch
await startWatchChanges();
await startWatchPlugins();
})();