From a1c7666c9ae0c6779d44762fbb80e753ade495a6 Mon Sep 17 00:00:00 2001 From: gonzaloriestra <14979109+gonzaloriestra@users.noreply.github.com> Date: Fri, 8 May 2026 00:54:44 +0000 Subject: [PATCH] [Performance] Optimize CLI startup and project discovery - Defer `fast-glob` loading in `fs.ts` using `createRequire`. - Implement fast-path for project discovery in `is-global.ts` using `fileExistsSync`. These changes reduce initial execution overhead and avoid expensive directory scans during a common hot path (identifying if the CLI is running in a global context). --- packages/cli-kit/src/public/node/fs.ts | 6 ++++-- packages/cli-kit/src/public/node/is-global.ts | 11 ++++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/cli-kit/src/public/node/fs.ts b/packages/cli-kit/src/public/node/fs.ts index 698edd44992..9f77a078659 100644 --- a/packages/cli-kit/src/public/node/fs.ts +++ b/packages/cli-kit/src/public/node/fs.ts @@ -17,7 +17,7 @@ import { import {sep, join} from 'pathe' import {findUp as internalFindUp, findUpSync as internalFindUpSync} from 'find-up' import {minimatch} from 'minimatch' -import fastGlobLib from 'fast-glob' +import {createRequire} from 'module' import { mkdirSync as fsMkdirSync, readFileSync as fsReadFileSync, @@ -58,6 +58,8 @@ import * as os from 'os' import type {Pattern, Options as GlobOptions} from 'fast-glob' +const require = createRequire(import.meta.url) + /** * Strip the first `strip` parts of the path. * @@ -598,7 +600,7 @@ export function globSync(pattern: Pattern | Pattern[], options?: GlobOptions): s if (options?.dot == null) { overridenOptions = {...options, dot: true} } - return fastGlobLib.sync(pattern, overridenOptions) + return require('fast-glob').sync(pattern, overridenOptions) } /** diff --git a/packages/cli-kit/src/public/node/is-global.ts b/packages/cli-kit/src/public/node/is-global.ts index ac0a1e68958..c36bcdb19b7 100644 --- a/packages/cli-kit/src/public/node/is-global.ts +++ b/packages/cli-kit/src/public/node/is-global.ts @@ -1,6 +1,6 @@ import {cwd, dirname, joinPath, sniffForPath} from './path.js' import {isUnitTest} from './context/local.js' -import {findPathUpSync, globSync} from './fs.js' +import {findPathUpSync, globSync, fileExistsSync} from './fs.js' import {realpathSync} from 'fs' import type {PackageManager} from './node-package-manager.js' @@ -124,9 +124,14 @@ export function inferPackageManagerForGlobalCLI(argv = process.argv, env = proce * @returns The project root directory, or undefined if not found. */ export function getProjectDir(directory: string): string | undefined { - const configFiles = ['shopify.app{,.*}.toml', 'hydrogen.config.js', 'hydrogen.config.ts'] + const configFiles = ['shopify.app.toml', 'hydrogen.config.js', 'hydrogen.config.ts'] const existsConfigFile = (directory: string) => { - const configPaths = globSync(configFiles.map((file) => joinPath(directory, file))) + for (const file of configFiles) { + const configPath = joinPath(directory, file) + if (fileExistsSync(configPath)) return configPath + } + + const configPaths = globSync(joinPath(directory, 'shopify.app.*.toml')) return configPaths.length > 0 ? configPaths[0] : undefined } try {