Merge pull request #485 from spotify/rugvip/cli-speed

packages/cli: lazy-load commands to speed up cli boot time
This commit is contained in:
Patrik Oldsberg
2020-04-07 11:53:14 +02:00
committed by GitHub
2 changed files with 34 additions and 33 deletions
+20 -12
View File
@@ -27,25 +27,33 @@ if (!isLocal) {
// This is a solution for getting src-relative imports to work with typescript/node in
// the published package. We're using `module: "amd"` to ship the entire cli implementation
// in one file, and it also happens to generate correct module definition and import statements.
// Minimal AMD implementation
const moduleFactories = {};
const moduleCache = {};
global.define = (name, deps, moduleFunc) => {
moduleFactories[name] = () => {
const exportsObj = {};
const impls = deps.slice(2).map(dep => {
const factory = moduleFactories[dep];
if (!factory) {
return require(dep);
}
if (!moduleCache[dep]) {
moduleCache[dep] = factory();
}
return moduleCache[dep];
});
moduleFunc(require, exportsObj, ...impls);
// require() that first searches for locally defined amd modules
const requireFunc = name => {
let factory = moduleFactories[name];
if (!factory) {
// Check /index as well, to mirror nodejs resolution
const index = `${name}/index`;
if (!moduleFactories[index]) {
return require(name);
}
name = index;
factory = moduleFactories[name];
}
if (!moduleCache[name]) {
moduleCache[name] = factory();
}
return moduleCache[name];
};
const impls = deps.slice(2).map(requireFunc);
moduleFunc(requireFunc, exportsObj, ...impls);
return exportsObj;
};
+14 -21
View File
@@ -16,16 +16,6 @@
import program from 'commander';
import chalk from 'chalk';
import createAppCommand from './commands/create-app/createApp';
import createPluginCommand from './commands/create-plugin/createPlugin';
import watch from './commands/watch-deps';
import buildCache from './commands/build-cache';
import lintCommand from './commands/lint';
import testCommand from './commands/testCommand';
import appBuild from './commands/app/build';
import appServe from './commands/app/serve';
import pluginBuild from './commands/plugin/build';
import pluginServe from './commands/plugin/serve';
import { exitWithError } from './helpers/errors';
import { paths } from './helpers/paths';
@@ -37,51 +27,53 @@ const main = (argv: string[]) => {
program
.command('create-app')
.description('Creates a new app in a new directory')
.action(actionHandler(createAppCommand));
.action(actionHandler(() => require('commands/create-app/createApp')));
program
.command('app:build')
.description('Build an app for a production release')
.action(actionHandler(appBuild));
.action(actionHandler(() => require('commands/app/build')));
program
.command('app:serve')
.description('Serve an app for local development')
.action(actionHandler(appServe));
.action(actionHandler(() => require('commands/app/serve')));
program
.command('create-plugin')
.description('Creates a new plugin in the current repository')
.action(actionHandler(createPluginCommand));
.action(
actionHandler(() => require('commands/create-plugin/createPlugin')),
);
program
.command('plugin:build')
.option('--watch', 'Enable watch mode')
.description('Build a plugin')
.action(actionHandler(pluginBuild));
.action(actionHandler(() => require('commands/plugin/build')));
program
.command('plugin:serve')
.description('Serves the dev/ folder of a plugin')
.action(actionHandler(pluginServe));
.action(actionHandler(() => require('commands/plugin/serve')));
program
.command('lint')
.option('--fix', 'Attempt to automatically fix violations')
.description('Lint a package')
.action(actionHandler(lintCommand));
.action(actionHandler(() => require('commands/lint')));
program
.command('test')
.option('--watch', 'Enable watch mode')
.option('--coverage', 'Report test coverage')
.description('Run all tests for package')
.action(actionHandler(testCommand));
.action(actionHandler(() => require('commands/testCommand')));
program
.command('watch-deps')
.description('Watch all dependencies while running another command')
.action(actionHandler(watch));
.action(actionHandler(() => require('commands/watch-deps')));
program
.command('build-cache')
@@ -98,7 +90,7 @@ const main = (argv: string[]) => {
'Cache dir',
'<repoRoot>/node_modules/.cache/backstage-builds',
)
.action(actionHandler(buildCache));
.action(actionHandler(() => require('commands/build-cache')));
program.on('command:*', () => {
console.log();
@@ -119,10 +111,11 @@ const main = (argv: string[]) => {
// Wraps an action function so that it always exits and handles errors
function actionHandler<T extends readonly any[]>(
actionFunc: (...args: T) => Promise<any>,
actionRequireFunc: () => { default(...args: T): Promise<any> },
): (...args: T) => Promise<never> {
return async (...args: T) => {
try {
const actionFunc = actionRequireFunc().default;
await actionFunc(...args);
process.exit(0);
} catch (error) {