From 42d8fc2bc752835159bf7829969dfaaea9279110 Mon Sep 17 00:00:00 2001 From: Chris Huber Date: Thu, 22 Oct 2026 23:37:35 -0400 Subject: [PATCH] Studio CLI: Import each date-fns function from its own path The date-fns root loads all of its functions, about 300 modules, on every studio command. Each function has its own path. --- apps/cli/commands/preview/list.ts | 2 +- apps/cli/commands/preview/update.ts | 2 +- apps/cli/lib/site-runtime-stats.ts | 2 +- apps/cli/lib/snapshots.ts | 6 +++++- apps/cli/tests/startup-imports.test.ts | 11 ++++++++++- packages/common/lib/bump-stat.ts | 4 +++- packages/common/lib/generate-backup-filename.ts | 2 +- 7 files changed, 22 insertions(+), 7 deletions(-) diff --git a/apps/cli/commands/preview/list.ts b/apps/cli/commands/preview/list.ts index 1edb8474f4..7b690d5d41 100644 --- a/apps/cli/commands/preview/list.ts +++ b/apps/cli/commands/preview/list.ts @@ -3,7 +3,7 @@ import { PreviewCommandLoggerAction as LoggerAction } from '@studio/common/logge import { Snapshot } from '@studio/common/types/snapshot'; import { __, _n, sprintf } from '@wordpress/i18n'; import CliTable3 from 'cli-table3'; -import { format } from 'date-fns'; +import { format } from 'date-fns/format'; import { readCliConfig } from 'cli/lib/cli-config/core'; import { getSiteByFolder } from 'cli/lib/cli-config/sites'; import { diff --git a/apps/cli/commands/preview/update.ts b/apps/cli/commands/preview/update.ts index 47dbba67f7..cf62b5efe8 100644 --- a/apps/cli/commands/preview/update.ts +++ b/apps/cli/commands/preview/update.ts @@ -7,7 +7,7 @@ import { readAuthToken } from '@studio/common/lib/shared-config'; import { PreviewCommandLoggerAction as LoggerAction } from '@studio/common/logger-actions'; import { Snapshot } from '@studio/common/types/snapshot'; import { __, _n, sprintf } from '@wordpress/i18n'; -import { addDays } from 'date-fns'; +import { addDays } from 'date-fns/addDays'; import { uploadArchive, waitForSiteReady } from 'cli/lib/api'; import { cleanup, archiveSiteContent } from 'cli/lib/archive'; import { getSiteByFolder } from 'cli/lib/cli-config/sites'; diff --git a/apps/cli/lib/site-runtime-stats.ts b/apps/cli/lib/site-runtime-stats.ts index 023605359b..849729d0ed 100644 --- a/apps/cli/lib/site-runtime-stats.ts +++ b/apps/cli/lib/site-runtime-stats.ts @@ -3,7 +3,7 @@ import { SITE_FILE_ACCESS_ALL_FILES, type SiteFileAccess, } from '@studio/common/lib/site-file-access'; -import { isSameDay } from 'date-fns'; +import { isSameDay } from 'date-fns/isSameDay'; import { bumpStat } from 'cli/lib/bump-stat'; import { lockCliConfig, diff --git a/apps/cli/lib/snapshots.ts b/apps/cli/lib/snapshots.ts index de9bbb2027..060cf4f6f0 100644 --- a/apps/cli/lib/snapshots.ts +++ b/apps/cli/lib/snapshots.ts @@ -1,6 +1,10 @@ import { HOUR_MS, DAY_MS, DEMO_SITE_EXPIRATION_DAYS } from '@studio/common/constants'; import { __ } from '@wordpress/i18n'; -import { addDays, addHours, DurationUnit, formatDuration, intervalToDuration } from 'date-fns'; +import { addDays } from 'date-fns/addDays'; +import { addHours } from 'date-fns/addHours'; +import { formatDuration } from 'date-fns/formatDuration'; +import { intervalToDuration } from 'date-fns/intervalToDuration'; +import type { DurationUnit } from 'date-fns'; export { getSnapshotsFromConfig, diff --git a/apps/cli/tests/startup-imports.test.ts b/apps/cli/tests/startup-imports.test.ts index 151fcc8ac2..e3d06f5b99 100644 --- a/apps/cli/tests/startup-imports.test.ts +++ b/apps/cli/tests/startup-imports.test.ts @@ -3,16 +3,24 @@ import path from 'path'; import { describe, expect, it, vi } from 'vitest'; const agentRuntimeLoaded = vi.hoisted( () => ( { value: false } ) ); +const dateFnsRootLoaded = vi.hoisted( () => ( { value: false } ) ); vi.mock( '@earendil-works/pi-coding-agent', () => { agentRuntimeLoaded.value = true; return {}; } ); +// The `date-fns` root loads every one of its functions, about 300 modules, which took +// about 0.9 s in the packaged app. Each function has its own path, e.g. `date-fns/format`. +vi.mock( 'date-fns', () => { + dateFnsRootLoaded.value = true; + return {}; +} ); + // Every `studio` command loads what the CLI entry imports statically before it // runs. The agent runtime is large, so only the commands that use it load it. describe( 'CLI startup', () => { - it( 'loads no agent runtime before a command runs', async () => { + it( 'loads no agent runtime or date-fns root before a command runs', async () => { const entry = readFileSync( path.join( import.meta.dirname, '..', 'index.ts' ), 'utf8' ); const staticImports = [ ...entry.matchAll( /^import [^;]*? from '(cli\/[^']+)';$/gm ) ].map( ( [ , specifier ] ) => specifier @@ -24,5 +32,6 @@ describe( 'CLI startup', () => { } expect( agentRuntimeLoaded.value ).toBe( false ); + expect( dateFnsRootLoaded.value ).toBe( false ); } ); } ); diff --git a/packages/common/lib/bump-stat.ts b/packages/common/lib/bump-stat.ts index ea5dda271f..91343b93d9 100644 --- a/packages/common/lib/bump-stat.ts +++ b/packages/common/lib/bump-stat.ts @@ -1,4 +1,6 @@ -import { isSameDay, isSameMonth, isSameWeek } from 'date-fns'; +import { isSameDay } from 'date-fns/isSameDay'; +import { isSameMonth } from 'date-fns/isSameMonth'; +import { isSameWeek } from 'date-fns/isSameWeek'; // Database columns are varchar(32). Group limit is 27 to account for the '-a11n' suffix // added by the backend for Automattic requests (27 + 5 = 32). diff --git a/packages/common/lib/generate-backup-filename.ts b/packages/common/lib/generate-backup-filename.ts index 7ea446b31c..087cb5b895 100644 --- a/packages/common/lib/generate-backup-filename.ts +++ b/packages/common/lib/generate-backup-filename.ts @@ -1,4 +1,4 @@ -import { format } from 'date-fns'; +import { format } from 'date-fns/format'; import { sanitizeFolderName } from '@studio/common/lib/sanitize-folder-name'; export function generateBackupFilename( name: string ) {