Watch and rebuild plugins
Summary: Now, once we build all plugins before we start Flipper, we need to rebuild some of them when they change. Previously, it was handled by Metro when we included plugins int he bundle, but we no longer include them in the bundle. Reviewed By: lblasa Differential Revision: D39510213 fbshipit-source-id: a352d78946f844a25d9127ac09c26e43e6739ca9
This commit is contained in:
committed by
Facebook GitHub Bot
parent
9dda947371
commit
3639feef61
@@ -37,6 +37,7 @@ import {
|
|||||||
import pFilter from 'p-filter';
|
import pFilter from 'p-filter';
|
||||||
import child from 'child_process';
|
import child from 'child_process';
|
||||||
import pMap from 'p-map';
|
import pMap from 'p-map';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
const dev = process.env.NODE_ENV !== 'production';
|
const dev = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
@@ -510,3 +511,17 @@ function defaultResolve(...rest: any[]) {
|
|||||||
...rest,
|
...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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -362,9 +362,6 @@ async function startWatchChanges(io: socketIo.Server) {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
await startWatchPlugins(() => {
|
|
||||||
io.emit('refresh');
|
|
||||||
});
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(
|
console.error(
|
||||||
'Failed to start watching for changes using Watchman, continue without hot reloading',
|
'Failed to start watching for changes using Watchman, continue without hot reloading',
|
||||||
@@ -448,6 +445,9 @@ function checkDevServer() {
|
|||||||
await startMetroServer(app, server);
|
await startMetroServer(app, server);
|
||||||
outputScreen(socket);
|
outputScreen(socket);
|
||||||
await compileMain();
|
await compileMain();
|
||||||
|
await startWatchPlugins(() => {
|
||||||
|
socket.emit('refresh');
|
||||||
|
});
|
||||||
if (dotenv && dotenv.parsed) {
|
if (dotenv && dotenv.parsed) {
|
||||||
console.log('✅ Loaded env vars from .env file: ', dotenv.parsed);
|
console.log('✅ Loaded env vars from .env file: ', dotenv.parsed);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import Watchman from './watchman';
|
|||||||
import isFB from './isFB';
|
import isFB from './isFB';
|
||||||
import yargs from 'yargs';
|
import yargs from 'yargs';
|
||||||
import ensurePluginFoldersWatchable from './ensurePluginFoldersWatchable';
|
import ensurePluginFoldersWatchable from './ensurePluginFoldersWatchable';
|
||||||
|
import startWatchPlugins from './startWatchPlugins';
|
||||||
|
|
||||||
const argv = yargs
|
const argv = yargs
|
||||||
.usage('yarn flipper-server [args]')
|
.usage('yarn flipper-server [args]')
|
||||||
@@ -149,12 +150,15 @@ async function startWatchChanges() {
|
|||||||
// For UI changes, Metro / hot module reloading / fast refresh take care of the changes
|
// For UI changes, Metro / hot module reloading / fast refresh take care of the changes
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
[
|
[
|
||||||
'pkg',
|
|
||||||
'doctor',
|
'doctor',
|
||||||
|
'pkg-lib',
|
||||||
'plugin-lib',
|
'plugin-lib',
|
||||||
'flipper-server',
|
|
||||||
'flipper-common',
|
'flipper-common',
|
||||||
|
'flipper-frontend-core',
|
||||||
|
'flipper-plugin-core',
|
||||||
|
'flipper-server-companion',
|
||||||
'flipper-server-core',
|
'flipper-server-core',
|
||||||
|
'flipper-server',
|
||||||
].map((dir) =>
|
].map((dir) =>
|
||||||
watchman.startWatchFiles(
|
watchman.startWatchFiles(
|
||||||
dir,
|
dir,
|
||||||
@@ -191,4 +195,5 @@ async function startWatchChanges() {
|
|||||||
await restartServer();
|
await restartServer();
|
||||||
// watch
|
// watch
|
||||||
await startWatchChanges();
|
await startWatchChanges();
|
||||||
|
await startWatchPlugins();
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -8,23 +8,49 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Watchman from './watchman';
|
import Watchman from './watchman';
|
||||||
import {getPluginSourceFolders} from 'flipper-plugin-lib';
|
import {getPluginSourceFolders, isPluginDir} from 'flipper-plugin-lib';
|
||||||
|
import path from 'path';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import {rebuildPlugin} from './build-utils';
|
||||||
|
|
||||||
export default async function startWatchPlugins(
|
export default async function startWatchPlugins(
|
||||||
onChanged: () => void | Promise<void>,
|
onChanged?: () => void | Promise<void>,
|
||||||
) {
|
) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('🕵️ Watching for plugin changes');
|
console.log('🕵️ Watching for plugin changes');
|
||||||
|
|
||||||
let delayedCompilation: NodeJS.Timeout | undefined;
|
let delayedCompilation: NodeJS.Timeout | undefined;
|
||||||
const kCompilationDelayMillis = 1000;
|
const kCompilationDelayMillis = 1000;
|
||||||
const onPluginChangeDetected = () => {
|
const onPluginChangeDetected = (root: string, files: string[]) => {
|
||||||
if (!delayedCompilation) {
|
if (!delayedCompilation) {
|
||||||
delayedCompilation = setTimeout(() => {
|
delayedCompilation = setTimeout(async () => {
|
||||||
delayedCompilation = undefined;
|
delayedCompilation = undefined;
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log(`🕵️ Detected plugin change`);
|
console.log(`🕵️ Detected plugin change`);
|
||||||
onChanged();
|
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);
|
||||||
|
let dirPath = path.dirname(filePathAbs);
|
||||||
|
while (
|
||||||
|
// Stop when we reach plugin root
|
||||||
|
!(await isPluginDir(dirPath))
|
||||||
|
) {
|
||||||
|
const relative = path.relative(root, dirPath);
|
||||||
|
// Stop when we reach desktop/plugins folder
|
||||||
|
if (!relative || relative.startsWith('..')) {
|
||||||
|
console.warn(
|
||||||
|
chalk.yellow('Failed to find a plugin root for path'),
|
||||||
|
filePathAbs,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dirPath = path.resolve(dirPath, '..');
|
||||||
|
}
|
||||||
|
await rebuildPlugin(dirPath);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
onChanged?.();
|
||||||
}, kCompilationDelayMillis);
|
}, kCompilationDelayMillis);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -38,15 +64,26 @@ export default async function startWatchPlugins(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function startWatchingPluginsUsingWatchman(onChange: () => void) {
|
async function startWatchingPluginsUsingWatchman(
|
||||||
|
onChange: (root: string, files: string[]) => void,
|
||||||
|
) {
|
||||||
const pluginFolders = await getPluginSourceFolders();
|
const pluginFolders = await getPluginSourceFolders();
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
pluginFolders.map(async (pluginFolder) => {
|
pluginFolders.map(async (pluginFolder) => {
|
||||||
const watchman = new Watchman(pluginFolder);
|
const watchman = new Watchman(pluginFolder);
|
||||||
await watchman.initialize();
|
await watchman.initialize();
|
||||||
await watchman.startWatchFiles('.', () => onChange(), {
|
await watchman.startWatchFiles(
|
||||||
excludes: ['**/__tests__/**/*', '**/node_modules/**/*', '**/.*'],
|
'.',
|
||||||
});
|
({files}) => onChange(pluginFolder, files),
|
||||||
|
{
|
||||||
|
excludes: [
|
||||||
|
'**/__tests__/**/*',
|
||||||
|
'**/node_modules/**/*',
|
||||||
|
'**/dist/*',
|
||||||
|
'**/.*',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user