From ec2f4974203fd5869c725cc455135cf56517404f Mon Sep 17 00:00:00 2001 From: Michael Bromley Date: Tue, 9 Apr 2024 15:45:58 +0200 Subject: [PATCH] perf(cli): Lazy load commands to improve startup time Makes add/help command about 2 seconds faster to run --- packages/cli/src/cli.ts | 22 +++- packages/cli/src/commands/add/add.ts | 103 +++++++++---------- packages/cli/src/commands/migrate/migrate.ts | 77 +++++++------- 3 files changed, 100 insertions(+), 102 deletions(-) diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 8805f29a98..3bf88b30bc 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -3,9 +3,6 @@ import { Command } from 'commander'; import pc from 'picocolors'; -import { registerAddCommand } from './commands/add/add'; -import { registerMigrateCommand } from './commands/migrate/migrate'; - const program = new Command(); // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -27,7 +24,22 @@ Y88 88P 88888888 888 888 888 888 888 888 888 88888888 `), ); -registerAddCommand(program); -registerMigrateCommand(program); +program + .command('add') + .description('Add a feature to your Vendure project') + .action(async () => { + const { addCommand } = await import('./commands/add/add'); + await addCommand(); + process.exit(0); + }); + +program + .command('migrate') + .description('Generate, run or revert a database migration') + .action(async () => { + const { migrateCommand } = await import('./commands/migrate/migrate'); + await migrateCommand(); + process.exit(0); + }); void program.parseAsync(process.argv); diff --git a/packages/cli/src/commands/add/add.ts b/packages/cli/src/commands/add/add.ts index 1cd9a9cf50..7bae1cb19f 100644 --- a/packages/cli/src/commands/add/add.ts +++ b/packages/cli/src/commands/add/add.ts @@ -1,5 +1,4 @@ import { cancel, intro, isCancel, log, outro, select, spinner } from '@clack/prompts'; -import { Command } from 'commander'; import pc from 'picocolors'; import { Messages } from '../../constants'; @@ -16,60 +15,54 @@ import { addUiExtensionsCommand } from './ui-extensions/add-ui-extensions'; const cancelledMessage = 'Add feature cancelled.'; -export function registerAddCommand(program: Command) { - program - .command('add') - .description('Add a feature to your Vendure project') - .action(async () => { - // eslint-disable-next-line no-console - console.log(`\n`); - intro(pc.blue("✨ Let's add a new feature to your Vendure project!")); - const addCommands: Array> = [ - createNewPluginCommand, - addEntityCommand, - addServiceCommand, - addApiExtensionCommand, - addJobQueueCommand, - addUiExtensionsCommand, - addCodegenCommand, - ]; - const featureType = await select({ - message: 'Which feature would you like to add?', - options: addCommands.map(c => ({ - value: c.id, - label: `[${c.category}] ${c.description}`, - })), - }); - if (isCancel(featureType)) { - cancel(cancelledMessage); - process.exit(0); - } - try { - const command = addCommands.find(c => c.id === featureType); - if (!command) { - throw new Error(`Could not find command with id "${featureType as string}"`); - } - const { modifiedSourceFiles, project } = await command.run(); +export async function addCommand() { + // eslint-disable-next-line no-console + console.log(`\n`); + intro(pc.blue("✨ Let's add a new feature to your Vendure project!")); + const addCommands: Array> = [ + createNewPluginCommand, + addEntityCommand, + addServiceCommand, + addApiExtensionCommand, + addJobQueueCommand, + addUiExtensionsCommand, + addCodegenCommand, + ]; + const featureType = await select({ + message: 'Which feature would you like to add?', + options: addCommands.map(c => ({ + value: c.id, + label: `[${c.category}] ${c.description}`, + })), + }); + if (isCancel(featureType)) { + cancel(cancelledMessage); + process.exit(0); + } + try { + const command = addCommands.find(c => c.id === featureType); + if (!command) { + throw new Error(`Could not find command with id "${featureType as string}"`); + } + const { modifiedSourceFiles, project } = await command.run(); - if (modifiedSourceFiles.length) { - const importsSpinner = spinner(); - importsSpinner.start('Organizing imports...'); - await pauseForPromptDisplay(); - for (const sourceFile of modifiedSourceFiles) { - sourceFile.organizeImports(); - } - await project.save(); - importsSpinner.stop('Imports organized'); - } - outro('✅ Done!'); - } catch (e: any) { - log.error(e.message as string); - const isCliMessage = Object.values(Messages).includes(e.message); - if (!isCliMessage && e.stack) { - log.error(e.stack); - } - outro('❌ Error'); + if (modifiedSourceFiles.length) { + const importsSpinner = spinner(); + importsSpinner.start('Organizing imports...'); + await pauseForPromptDisplay(); + for (const sourceFile of modifiedSourceFiles) { + sourceFile.organizeImports(); } - process.exit(0); - }); + await project.save(); + importsSpinner.stop('Imports organized'); + } + outro('✅ Done!'); + } catch (e: any) { + log.error(e.message as string); + const isCliMessage = Object.values(Messages).includes(e.message); + if (!isCliMessage && e.stack) { + log.error(e.stack); + } + outro('❌ Error'); + } } diff --git a/packages/cli/src/commands/migrate/migrate.ts b/packages/cli/src/commands/migrate/migrate.ts index 1e49d802b8..52c37ac43e 100644 --- a/packages/cli/src/commands/migrate/migrate.ts +++ b/packages/cli/src/commands/migrate/migrate.ts @@ -1,5 +1,4 @@ import { cancel, intro, isCancel, log, outro, select } from '@clack/prompts'; -import { Command } from 'commander'; import pc from 'picocolors'; import { generateMigrationCommand } from './generate-migration/generate-migration'; @@ -13,45 +12,39 @@ const cancelledMessage = 'Migrate cancelled.'; * peculiarities in loading ESM modules vs CommonJS modules. More time is needed to dig into * this before we expose this command in the cli.ts file. */ -export function registerMigrateCommand(program: Command) { - program - .command('migrate') - .description('Generate, run or revert a database migration') - .action(async () => { - // eslint-disable-next-line no-console - console.log(`\n`); - intro(pc.blue('🛠️️ Vendure migrations')); - const action = await select({ - message: 'What would you like to do?', - options: [ - { value: 'generate', label: 'Generate a new migration' }, - { value: 'run', label: 'Run pending migrations' }, - { value: 'revert', label: 'Revert the last migration' }, - ], - }); - if (isCancel(action)) { - cancel(cancelledMessage); - process.exit(0); - } - try { - process.env.VENDURE_RUNNING_IN_CLI = 'true'; - if (action === 'generate') { - await generateMigrationCommand.run(); - } - if (action === 'run') { - await runMigrationCommand.run(); - } - if (action === 'revert') { - await revertMigrationCommand.run(); - } - outro('✅ Done!'); - process.env.VENDURE_RUNNING_IN_CLI = undefined; - } catch (e: any) { - log.error(e.message as string); - if (e.stack) { - log.error(e.stack); - } - } - process.exit(0); - }); +export async function migrateCommand() { + // eslint-disable-next-line no-console + console.log(`\n`); + intro(pc.blue('🛠️️ Vendure migrations')); + const action = await select({ + message: 'What would you like to do?', + options: [ + { value: 'generate', label: 'Generate a new migration' }, + { value: 'run', label: 'Run pending migrations' }, + { value: 'revert', label: 'Revert the last migration' }, + ], + }); + if (isCancel(action)) { + cancel(cancelledMessage); + process.exit(0); + } + try { + process.env.VENDURE_RUNNING_IN_CLI = 'true'; + if (action === 'generate') { + await generateMigrationCommand.run(); + } + if (action === 'run') { + await runMigrationCommand.run(); + } + if (action === 'revert') { + await revertMigrationCommand.run(); + } + outro('✅ Done!'); + process.env.VENDURE_RUNNING_IN_CLI = undefined; + } catch (e: any) { + log.error(e.message as string); + if (e.stack) { + log.error(e.stack); + } + } }