From d755ee151ba9ebfe8fe17b3f28e8cd6b865103c0 Mon Sep 17 00:00:00 2001 From: bluwy Date: Tue, 27 Aug 2024 17:15:10 +0800 Subject: [PATCH 1/2] Use tinyexec --- .changeset/four-beans-remember.md | 5 +++++ benchmark/bench/cli-startup.js | 13 ++++++------ benchmark/bench/memory.js | 14 ++++++------ benchmark/bench/render.js | 18 ++++++++++------ benchmark/bench/server-stress.js | 10 +++++---- benchmark/package.json | 4 ++-- packages/astro/package.json | 3 ++- packages/astro/src/cli/add/index.ts | 14 ++++++------ packages/astro/src/cli/docs/open.ts | 7 +++--- packages/astro/src/cli/install-package.ts | 10 ++++----- pnpm-lock.yaml | 26 +++++++++++++++-------- scripts/package.json | 2 +- scripts/smoke/cleanup.js | 6 ++++-- scripts/smoke/index.js | 14 ++++++------ 14 files changed, 87 insertions(+), 59 deletions(-) create mode 100644 .changeset/four-beans-remember.md diff --git a/.changeset/four-beans-remember.md b/.changeset/four-beans-remember.md new file mode 100644 index 000000000000..cdef7197d15c --- /dev/null +++ b/.changeset/four-beans-remember.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Replaces `execa` with `tinyexec` internally diff --git a/benchmark/bench/cli-startup.js b/benchmark/bench/cli-startup.js index aa8880554e0c..6f25554997cd 100644 --- a/benchmark/bench/cli-startup.js +++ b/benchmark/bench/cli-startup.js @@ -1,5 +1,5 @@ import { fileURLToPath } from 'node:url'; -import { execaCommand } from 'execa'; +import { exec } from 'tinyexec'; import { markdownTable } from 'markdown-table'; import { astroBin, calculateStat } from './_util.js'; @@ -14,11 +14,11 @@ export async function run(projectDir, outputFile) { const root = fileURLToPath(projectDir); console.log('Benchmarking `astro --help`...'); - const helpStat = await benchmarkCommand(`node ${astroBin} --help`, root); + const helpStat = await benchmarkCommand('node', [astroBin, '--help'], root); console.log('Done'); - console.log('Benchmarking `astro info`...'); - const infoStat = await benchmarkCommand(`node ${astroBin} info`, root); + console.log('Benchmarking `astro preferences list`...'); + const infoStat = await benchmarkCommand('node', [astroBin, 'preferences', 'list'], root); console.log('Done'); console.log('Result preview:'); @@ -35,16 +35,17 @@ export async function run(projectDir, outputFile) { /** * @param {string} command + * @param {string[]} args * @param {string} root * @returns {Promise} */ -async function benchmarkCommand(command, root) { +async function benchmarkCommand(command, args, root) { /** @type {number[]} */ const durations = []; for (let i = 0; i < 10; i++) { const start = performance.now(); - await execaCommand(command, { cwd: root }); + await exec(command, args, { nodeOptions: { cwd: root } }); durations.push(performance.now() - start); } diff --git a/benchmark/bench/memory.js b/benchmark/bench/memory.js index 3a437b3fe357..f1846204f8b9 100644 --- a/benchmark/bench/memory.js +++ b/benchmark/bench/memory.js @@ -1,4 +1,4 @@ -import { execaCommand } from 'execa'; +import { exec } from 'tinyexec'; import { markdownTable } from 'markdown-table'; import fs from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; @@ -18,11 +18,13 @@ export async function run(projectDir, outputFile) { const outputFilePath = fileURLToPath(outputFile); console.log('Building and benchmarking...'); - await execaCommand(`node --expose-gc --max_old_space_size=10000 ${astroBin} build --silent`, { - cwd: root, - stdio: 'inherit', - env: { - ASTRO_TIMER_PATH: outputFilePath, + await exec('node', ['--expose-gc', '--max_old_space_size=10000', astroBin, 'build'], { + nodeOptions: { + cwd: root, + stdio: 'inherit', + env: { + ASTRO_TIMER_PATH: outputFilePath, + }, }, }); diff --git a/benchmark/bench/render.js b/benchmark/bench/render.js index 20c9abb0f3a3..aee04f2b5bed 100644 --- a/benchmark/bench/render.js +++ b/benchmark/bench/render.js @@ -1,4 +1,4 @@ -import { execaCommand } from 'execa'; +import { exec } from 'tinyexec'; import { markdownTable } from 'markdown-table'; import fs from 'node:fs/promises'; import http from 'node:http'; @@ -20,15 +20,19 @@ export async function run(projectDir, outputFile) { const root = fileURLToPath(projectDir); console.log('Building...'); - await execaCommand(`${astroBin} build`, { - cwd: root, - stdio: 'inherit', + await exec(astroBin, ['build'], { + nodeOptions: { + cwd: root, + stdio: 'inherit', + }, }); console.log('Previewing...'); - const previewProcess = execaCommand(`${astroBin} preview --port ${port}`, { - cwd: root, - stdio: 'inherit', + const previewProcess = exec(astroBin, ['preview', '--port', port], { + nodeOptions: { + cwd: root, + stdio: 'inherit', + }, }); console.log('Waiting for server ready...'); diff --git a/benchmark/bench/server-stress.js b/benchmark/bench/server-stress.js index ca165e239a3a..18b31c71c59e 100644 --- a/benchmark/bench/server-stress.js +++ b/benchmark/bench/server-stress.js @@ -1,5 +1,5 @@ import autocannon from 'autocannon'; -import { execaCommand } from 'execa'; +import { exec } from 'tinyexec'; import { markdownTable } from 'markdown-table'; import fs from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; @@ -19,9 +19,11 @@ export async function run(projectDir, outputFile) { const root = fileURLToPath(projectDir); console.log('Building...'); - await execaCommand(`${astroBin} build`, { - cwd: root, - stdio: 'inherit', + await exec(astroBin, ['build'], { + nodeOptions: { + cwd: root, + stdio: 'inherit', + }, }); console.log('Previewing...'); diff --git a/benchmark/package.json b/benchmark/package.json index d56a6d1b0673..60c8621d2eb2 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -12,11 +12,11 @@ "@benchmark/timer": "workspace:*", "astro": "workspace:*", "autocannon": "^7.15.0", - "execa": "^8.0.1", "markdown-table": "^3.0.3", "mri": "^1.2.0", "port-authority": "^2.0.1", "pretty-bytes": "^6.1.1", - "sharp": "^0.33.3" + "sharp": "^0.33.3", + "tinyexec": "^0.3.0" } } diff --git a/packages/astro/package.json b/packages/astro/package.json index 5be4f81bbf32..0f33b4a92478 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -154,7 +154,6 @@ "es-module-lexer": "^1.5.4", "esbuild": "^0.21.5", "estree-walker": "^3.0.3", - "execa": "^8.0.1", "fast-glob": "^3.3.2", "flattie": "^1.1.1", "github-slugger": "^2.0.0", @@ -178,6 +177,7 @@ "shiki": "^1.14.1", "string-width": "^7.2.0", "strip-ansi": "^7.1.0", + "tinyexec": "^0.3.0", "tsconfck": "^3.1.1", "unist-util-visit": "^5.0.0", "vfile": "^6.0.2", @@ -216,6 +216,7 @@ "astro-scripts": "workspace:*", "cheerio": "1.0.0", "eol": "^0.9.1", + "execa": "^8.0.1", "expect-type": "^0.19.0", "mdast-util-mdx": "^3.0.0", "mdast-util-mdx-jsx": "^3.1.2", diff --git a/packages/astro/src/cli/add/index.ts b/packages/astro/src/cli/add/index.ts index f710184d2cb9..4b2cc81fa30e 100644 --- a/packages/astro/src/cli/add/index.ts +++ b/packages/astro/src/cli/add/index.ts @@ -3,12 +3,12 @@ import path from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; import boxen from 'boxen'; import { diffWords } from 'diff'; -import { execa } from 'execa'; import { bold, cyan, dim, green, magenta, red, yellow } from 'kleur/colors'; import ora from 'ora'; import preferredPM from 'preferred-pm'; import prompts from 'prompts'; import maxSatisfying from 'semver/ranges/max-satisfying.js'; +import { exec } from 'tinyexec'; import { loadTSConfig, resolveConfig, @@ -755,7 +755,7 @@ async function tryToInstallIntegrations({ if (await askToContinue({ flags })) { const spinner = ora('Installing dependencies...').start(); try { - await execa( + await exec( installCommand.pm, [ installCommand.command, @@ -764,10 +764,12 @@ async function tryToInstallIntegrations({ ...installCommand.dependencies, ], { - cwd, - // reset NODE_ENV to ensure install command run in dev mode - env: { NODE_ENV: undefined }, - }, + nodeOptions: { + cwd, + // reset NODE_ENV to ensure install command run in dev mode + env: { NODE_ENV: undefined }, + }, + } ); spinner.succeed(); return UpdateResult.updated; diff --git a/packages/astro/src/cli/docs/open.ts b/packages/astro/src/cli/docs/open.ts index 3913ccec4f57..6f2fe4c82117 100644 --- a/packages/astro/src/cli/docs/open.ts +++ b/packages/astro/src/cli/docs/open.ts @@ -1,5 +1,4 @@ -import type { ExecaChildProcess } from 'execa'; -import { execa } from 'execa'; +import { type Result, exec } from 'tinyexec'; /** * Credit: Azhar22 @@ -26,7 +25,7 @@ const getPlatformSpecificCommand = (): [string] | [string, string[]] => { } }; -export async function openInBrowser(url: string): Promise { +export async function openInBrowser(url: string): Promise { const [command, args = []] = getPlatformSpecificCommand(); - return execa(command, [...args, encodeURI(url)]); + return exec(command, [...args, encodeURI(url)]); } diff --git a/packages/astro/src/cli/install-package.ts b/packages/astro/src/cli/install-package.ts index 637390ef3c2c..46440b385fb9 100644 --- a/packages/astro/src/cli/install-package.ts +++ b/packages/astro/src/cli/install-package.ts @@ -1,11 +1,11 @@ import { createRequire } from 'node:module'; import boxen from 'boxen'; import ci from 'ci-info'; -import { execa } from 'execa'; import { bold, cyan, dim, magenta } from 'kleur/colors'; import ora from 'ora'; import preferredPM from 'preferred-pm'; import prompts from 'prompts'; +import { exec } from 'tinyexec'; import whichPm from 'which-pm'; import type { Logger } from '../core/logger/core.js'; @@ -141,10 +141,10 @@ async function installPackage( if (Boolean(response)) { const spinner = ora('Installing dependencies...').start(); try { - await execa( + await exec( installCommand.pm, [installCommand.command, ...installCommand.flags, ...installCommand.dependencies], - { cwd: cwd }, + { nodeOptions: { cwd: cwd } } ); spinner.succeed(); @@ -203,8 +203,8 @@ async function getRegistry(): Promise { const fallback = 'https://registry.npmjs.org'; const packageManager = (await preferredPM(process.cwd()))?.name || 'npm'; try { - const { stdout } = await execa(packageManager, ['config', 'get', 'registry']); - _registry = stdout?.trim()?.replace(/\/$/, '') || fallback; + const { stdout } = await exec(packageManager, ['config', 'get', 'registry']); + _registry = stdout.trim()?.replace(/\/$/, '') || fallback; // Detect cases where the shell command returned a non-URL (e.g. a warning) if (!new URL(_registry).host) _registry = fallback; } catch { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a0458718b933..23a409d5d1d2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -78,9 +78,6 @@ importers: autocannon: specifier: ^7.15.0 version: 7.15.0 - execa: - specifier: ^8.0.1 - version: 8.0.1 markdown-table: specifier: ^3.0.3 version: 3.0.3 @@ -96,6 +93,9 @@ importers: sharp: specifier: ^0.33.3 version: 0.33.3 + tinyexec: + specifier: ^0.3.0 + version: 0.3.0 benchmark/packages/timer: dependencies: @@ -651,9 +651,6 @@ importers: estree-walker: specifier: ^3.0.3 version: 3.0.3 - execa: - specifier: ^8.0.1 - version: 8.0.1 fast-glob: specifier: ^3.3.2 version: 3.3.2 @@ -723,6 +720,9 @@ importers: strip-ansi: specifier: ^7.1.0 version: 7.1.0 + tinyexec: + specifier: ^0.3.0 + version: 0.3.0 tsconfck: specifier: ^3.1.1 version: 3.1.1(typescript@5.5.4) @@ -827,6 +827,9 @@ importers: eol: specifier: ^0.9.1 version: 0.9.1 + execa: + specifier: ^8.0.1 + version: 8.0.1 expect-type: specifier: ^0.19.0 version: 0.19.0 @@ -5988,9 +5991,6 @@ importers: esbuild-plugin-copy: specifier: ^2.1.1 version: 2.1.1(esbuild@0.21.5) - execa: - specifier: ^8.0.1 - version: 8.0.1 fast-glob: specifier: ^3.3.2 version: 3.3.2 @@ -6000,6 +6000,9 @@ importers: p-limit: specifier: ^6.1.0 version: 6.1.0 + tinyexec: + specifier: ^0.3.0 + version: 0.3.0 tsconfck: specifier: ^3.1.1 version: 3.1.1(typescript@5.5.4) @@ -10982,6 +10985,9 @@ packages: tinybench@2.8.0: resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} + tinyexec@0.3.0: + resolution: {integrity: sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==} + tinypool@1.0.0: resolution: {integrity: sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ==} engines: {node: ^18.0.0 || >=20.0.0} @@ -17503,6 +17509,8 @@ snapshots: tinybench@2.8.0: {} + tinyexec@0.3.0: {} + tinypool@1.0.0: {} tinyrainbow@1.2.0: {} diff --git a/scripts/package.json b/scripts/package.json index 35bf517a6602..bbf3e970606e 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -10,10 +10,10 @@ "dependencies": { "esbuild": "^0.21.5", "esbuild-plugin-copy": "^2.1.1", - "execa": "^8.0.1", "fast-glob": "^3.3.2", "kleur": "^4.1.5", "p-limit": "^6.1.0", + "tinyexec": "^0.3.0", "tsconfck": "^3.1.1" } } diff --git a/scripts/smoke/cleanup.js b/scripts/smoke/cleanup.js index 3b03951f938f..1bb398d9e10e 100644 --- a/scripts/smoke/cleanup.js +++ b/scripts/smoke/cleanup.js @@ -2,7 +2,7 @@ // @ts-check -import { execa } from 'execa'; +import { exec } from 'tinyexec'; import { promises as fs } from 'node:fs'; import { fileURLToPath } from 'node:url'; @@ -36,7 +36,9 @@ async function run() { console.log('🤖', 'Resetting', 'pnpm'); - await execa('pnpm', ['install'], { cwd: fileURLToPath(rootDir), stdout: 'inherit', stderr: 'inherit' }); + await exec('pnpm', ['install'], { + nodeOptions: { cwd: fileURLToPath(rootDir), stdio: ['pipe', 'inherit', 'inherit'] }, + }); } /* Functionality diff --git a/scripts/smoke/index.js b/scripts/smoke/index.js index 7ab78e286eb3..49887cd2ee53 100644 --- a/scripts/smoke/index.js +++ b/scripts/smoke/index.js @@ -2,7 +2,7 @@ // @ts-check -import { execa } from 'execa'; +import { exec } from 'tinyexec'; import { promises as fs } from 'node:fs'; import { fileURLToPath } from 'node:url'; @@ -32,10 +32,12 @@ async function run() { console.log(''); const directories = [...(await getChildDirectories(smokeDir)), ...(await getChildDirectories(exampleDir))]; + /** @type {Partial} */ + const execOptions = { nodeOptions: { cwd: fileURLToPath(rootDir), stdio: 'inherit' }}; console.log('🤖', 'Preparing', 'pnpm'); - - await execa('pnpm', ['install', '--frozen-lockfile=false'], { cwd: fileURLToPath(rootDir), stdio: 'inherit' }); + + await exec('pnpm', ['install', '--frozen-lockfile=false'], execOptions); for (const directory of directories) { const name = directory.pathname.split('/').at(-1) ?? ""; @@ -43,9 +45,9 @@ async function run() { console.log('🤖', 'Testing', name); try { - await execa('pnpm', ['install', '--ignore-scripts', '--frozen-lockfile=false'].filter(x => x), { cwd: fileURLToPath(directory), stdio: 'inherit' }); - await execa('pnpm', ['astro', 'telemetry', 'disable']); - await execa('pnpm', ['run', 'build'], { cwd: fileURLToPath(directory), stdio: 'inherit' }); + await exec('pnpm', ['install', '--ignore-scripts', '--frozen-lockfile=false'], execOptions); + await exec('pnpm', ['astro', 'telemetry', 'disable']); + await exec('pnpm', ['run', 'build'], execOptions); } catch (err) { console.log(err); process.exit(1); From a85eedb0fbe789fc0d209d715acf88cfdaeece91 Mon Sep 17 00:00:00 2001 From: bluwy Date: Wed, 28 Aug 2024 22:32:32 +0800 Subject: [PATCH 2/2] Fix merge error --- packages/astro/package.json | 1 + pnpm-lock.yaml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/packages/astro/package.json b/packages/astro/package.json index 4358e59b2125..d7b0846bfe41 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -216,6 +216,7 @@ "astro-scripts": "workspace:*", "cheerio": "1.0.0", "eol": "^0.9.1", + "execa": "^8.0.1", "expect-type": "^0.20.0", "mdast-util-mdx": "^3.0.0", "mdast-util-mdx-jsx": "^3.1.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2bfe20c302c5..d6143ffb02e3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -827,6 +827,9 @@ importers: eol: specifier: ^0.9.1 version: 0.9.1 + execa: + specifier: ^8.0.1 + version: 8.0.1 expect-type: specifier: ^0.20.0 version: 0.20.0