From 23d296dd1e4a9835961c6213e8692d5cbd41fbf9 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 4 Jun 2025 16:14:55 +0200 Subject: [PATCH 1/9] test: add dev benchmark --- .github/workflows/ci.yml | 6 + package.json | 1 + packages/nuxt-cli/test/bench/dev.bench.ts | 29 +++++ pnpm-lock.yaml | 128 ++++++++++++++++++++++ vitest.config.ts | 2 + 5 files changed, 166 insertions(+) create mode 100644 packages/nuxt-cli/test/bench/dev.bench.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0604dbd3..e66aa4e4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,6 +63,12 @@ jobs: - name: 🧪 Test (unit) run: pnpm test:unit + - name: Run benchmarks + uses: CodSpeedHQ/action@0010eb0ca6e89b80c88e8edaaa07cfe5f3e6664d # v3.5.0 + with: + run: pnpm vitest bench + token: ${{ secrets.CODSPEED_TOKEN }} + - if: matrix.os != 'windows-latest' uses: codecov/codecov-action@v5 diff --git a/package.json b/package.json index 7499145bd..ff344fe9a 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ }, "devDependencies": { "@antfu/eslint-config": "^4.13.2", + "@codspeed/vitest-plugin": "^4.0.1", "@nuxt/eslint-config": "^1.4.1", "@types/node": "^22.15.29", "@types/semver": "^7.7.0", diff --git a/packages/nuxt-cli/test/bench/dev.bench.ts b/packages/nuxt-cli/test/bench/dev.bench.ts new file mode 100644 index 000000000..cfd5f4a3c --- /dev/null +++ b/packages/nuxt-cli/test/bench/dev.bench.ts @@ -0,0 +1,29 @@ +import { rm } from 'node:fs/promises' +import { join } from 'node:path' +import { fileURLToPath } from 'node:url' + +import { bench, describe } from 'vitest' + +import { runCommand } from '../../../nuxi/src/run' + +describe('dev', async () => { + const fixtureDir = fileURLToPath(new URL('../../playground', import.meta.url)) + await rm(join(fixtureDir, '.nuxt'), { recursive: true, force: true }) + + bench('starts dev server', async () => { + const { result } = await runCommand('dev', [fixtureDir], { + overrides: { + builder: { + bundle: (nuxt) => { + nuxt.hooks.removeAllHooks() + return Promise.resolve() + }, + }, + }, + }) + await (result as { listener: any }).listener.close() + }) + + // it.skip('makes requests to dev server', async () => { + // }) +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d7adc3fb4..c8fd3292b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,6 +21,9 @@ importers: '@antfu/eslint-config': specifier: ^4.13.2 version: 4.13.2(@typescript-eslint/utils@8.33.0(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3))(@vue/compiler-sfc@3.5.16)(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3)(vitest@3.2.0(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(terser@5.40.0)(yaml@2.8.0)) + '@codspeed/vitest-plugin': + specifier: ^4.0.1 + version: 4.0.1(vite@6.3.5(@types/node@22.15.29)(jiti@2.4.2)(terser@5.40.0)(yaml@2.8.0))(vitest@3.2.0(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(terser@5.40.0)(yaml@2.8.0)) '@nuxt/eslint-config': specifier: ^1.4.1 version: 1.4.1(@typescript-eslint/utils@8.33.0(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3))(@vue/compiler-sfc@3.5.16)(eslint@9.28.0(jiti@2.4.2))(typescript@5.8.3) @@ -497,6 +500,15 @@ packages: resolution: {integrity: sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==} engines: {node: '>=18.0.0'} + '@codspeed/core@4.0.1': + resolution: {integrity: sha512-fJ53arfgtzCDZa8DuGJhpTZ3Ll9A1uW5nQ2jSJnfO4Hl5MRD2cP8P4vPvIUAGbdbjwCxR1jat6cW8OloMJkJXw==} + + '@codspeed/vitest-plugin@4.0.1': + resolution: {integrity: sha512-aqmrPJzX9cD50UWDsOyih5L5WcEYlNQg3u84sJJ9ZuuLApA51w+LGxk6Xbyb8LJF9n/CwM94HKHV/qArfnvDoQ==} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + vitest: '>=1.2.2' + '@colors/colors@1.6.0': resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} @@ -2071,6 +2083,9 @@ packages: async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + autoprefixer@10.4.21: resolution: {integrity: sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==} engines: {node: ^10 || ^12 || >=14} @@ -2078,6 +2093,9 @@ packages: peerDependencies: postcss: ^8.1.0 + axios@1.9.0: + resolution: {integrity: sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==} + b4a@1.6.7: resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} @@ -2256,6 +2274,10 @@ packages: colorspace@1.1.4: resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} @@ -2482,6 +2504,10 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} @@ -2648,6 +2674,10 @@ packages: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + esbuild@0.25.4: resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==} engines: {node: '>=18'} @@ -3000,6 +3030,10 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} + find-up@6.3.0: + resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + find-up@7.0.0: resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} engines: {node: '>=18'} @@ -3017,10 +3051,23 @@ packages: fn.name@1.1.0: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + format@0.2.2: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} @@ -3171,6 +3218,10 @@ packages: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -3725,10 +3776,18 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + mime-db@1.54.0: resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} engines: {node: '>= 0.6'} + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + mime-types@3.0.1: resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==} engines: {node: '>= 0.6'} @@ -4370,6 +4429,9 @@ packages: protocols@2.0.2: resolution: {integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pump@3.0.2: resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} @@ -5658,6 +5720,23 @@ snapshots: dependencies: mime: 3.0.0 + '@codspeed/core@4.0.1': + dependencies: + axios: 1.9.0 + find-up: 6.3.0 + form-data: 4.0.2 + node-gyp-build: 4.8.4 + transitivePeerDependencies: + - debug + + '@codspeed/vitest-plugin@4.0.1(vite@6.3.5(@types/node@22.15.29)(jiti@2.4.2)(terser@5.40.0)(yaml@2.8.0))(vitest@3.2.0(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(terser@5.40.0)(yaml@2.8.0))': + dependencies: + '@codspeed/core': 4.0.1 + vite: 6.3.5(@types/node@22.15.29)(jiti@2.4.2)(terser@5.40.0)(yaml@2.8.0) + vitest: 3.2.0(@types/debug@4.1.12)(@types/node@22.15.29)(jiti@2.4.2)(terser@5.40.0)(yaml@2.8.0) + transitivePeerDependencies: + - debug + '@colors/colors@1.6.0': {} '@dabh/diagnostics@2.0.3': @@ -7352,6 +7431,8 @@ snapshots: async@3.2.6: {} + asynckit@0.4.0: {} + autoprefixer@10.4.21(postcss@8.5.4): dependencies: browserslist: 4.25.0 @@ -7362,6 +7443,14 @@ snapshots: postcss: 8.5.4 postcss-value-parser: 4.2.0 + axios@1.9.0: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + b4a@1.6.7: {} balanced-match@1.0.2: {} @@ -7560,6 +7649,10 @@ snapshots: color: 3.2.1 text-hex: 1.0.0 + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + commander@10.0.1: {} commander@12.1.0: {} @@ -7753,6 +7846,8 @@ snapshots: defu@6.1.4: {} + delayed-stream@1.0.0: {} + denque@2.1.0: {} depd@2.0.0: {} @@ -7904,6 +7999,13 @@ snapshots: dependencies: es-errors: 1.3.0 + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + esbuild@0.25.4: optionalDependencies: '@esbuild/aix-ppc64': 0.25.4 @@ -8376,6 +8478,11 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 + find-up@6.3.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + find-up@7.0.0: dependencies: locate-path: 7.2.0 @@ -8397,11 +8504,20 @@ snapshots: fn.name@1.1.0: {} + follow-redirects@1.15.9: {} + foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + format@0.2.2: {} formatly@0.2.3: @@ -8558,6 +8674,10 @@ snapshots: has-symbols@1.1.0: {} + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -9268,8 +9388,14 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mime-db@1.52.0: {} + mime-db@1.54.0: {} + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + mime-types@3.0.1: dependencies: mime-db: 1.54.0 @@ -10178,6 +10304,8 @@ snapshots: protocols@2.0.2: {} + proxy-from-env@1.1.0: {} + pump@3.0.2: dependencies: end-of-stream: 1.4.4 diff --git a/vitest.config.ts b/vitest.config.ts index a1d0b535d..ef90a2eea 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,6 +1,8 @@ +import codspeed from '@codspeed/vitest-plugin' import { defineConfig } from 'vitest/config' export default defineConfig({ + plugins: [codspeed()], test: { coverage: {}, }, From c3be6d66ea936d089ecb62832f8d1b011002c7d1 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 4 Jun 2025 16:15:18 +0200 Subject: [PATCH 2/9] test: add --no-fork test --- packages/nuxt-cli/test/bench/dev.bench.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/nuxt-cli/test/bench/dev.bench.ts b/packages/nuxt-cli/test/bench/dev.bench.ts index cfd5f4a3c..d2d6281c6 100644 --- a/packages/nuxt-cli/test/bench/dev.bench.ts +++ b/packages/nuxt-cli/test/bench/dev.bench.ts @@ -24,6 +24,20 @@ describe('dev', async () => { await (result as { listener: any }).listener.close() }) + bench('starts dev server in no-fork mode', async () => { + const { result } = await runCommand('dev', [fixtureDir, '--no-fork'], { + overrides: { + builder: { + bundle: (nuxt) => { + nuxt.hooks.removeAllHooks() + return Promise.resolve() + }, + }, + }, + }) + await (result as { listener: any }).listener.close() + }) + // it.skip('makes requests to dev server', async () => { // }) }) From 0c95f1b657ec5a27984541454a69dce8b692f2cb Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 4 Jun 2025 16:17:31 +0200 Subject: [PATCH 3/9] chore: add type --- packages/nuxt-cli/package.json | 1 + packages/nuxt-cli/test/bench/dev.bench.ts | 6 ++++-- pnpm-lock.yaml | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/nuxt-cli/package.json b/packages/nuxt-cli/package.json index de9a45f0a..b47ecedb0 100644 --- a/packages/nuxt-cli/package.json +++ b/packages/nuxt-cli/package.json @@ -59,6 +59,7 @@ "youch": "^4.1.0-beta.8" }, "devDependencies": { + "@nuxt/schema": "^3.17.5", "@types/node": "^22.15.29", "rollup": "^4.41.1", "rollup-plugin-visualizer": "^6.0.1", diff --git a/packages/nuxt-cli/test/bench/dev.bench.ts b/packages/nuxt-cli/test/bench/dev.bench.ts index d2d6281c6..1003906a1 100644 --- a/packages/nuxt-cli/test/bench/dev.bench.ts +++ b/packages/nuxt-cli/test/bench/dev.bench.ts @@ -1,3 +1,5 @@ +import type { Nuxt } from '@nuxt/schema' + import { rm } from 'node:fs/promises' import { join } from 'node:path' import { fileURLToPath } from 'node:url' @@ -14,7 +16,7 @@ describe('dev', async () => { const { result } = await runCommand('dev', [fixtureDir], { overrides: { builder: { - bundle: (nuxt) => { + bundle: (nuxt: Nuxt) => { nuxt.hooks.removeAllHooks() return Promise.resolve() }, @@ -28,7 +30,7 @@ describe('dev', async () => { const { result } = await runCommand('dev', [fixtureDir, '--no-fork'], { overrides: { builder: { - bundle: (nuxt) => { + bundle: (nuxt: Nuxt) => { nuxt.hooks.removeAllHooks() return Promise.resolve() }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c8fd3292b..25ce5796a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -287,6 +287,9 @@ importers: specifier: ^4.1.0-beta.8 version: 4.1.0-beta.8 devDependencies: + '@nuxt/schema': + specifier: ^3.17.5 + version: 3.17.5 '@types/node': specifier: ^22.15.29 version: 22.15.29 From 42b6ec0078d30695fa613b69ef4601111f499076 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 4 Jun 2025 16:25:38 +0200 Subject: [PATCH 4/9] test: add dev server requests benchmark --- packages/nuxt-cli/test/bench/dev.bench.ts | 15 +++++++++++++-- pnpm-lock.yaml | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/nuxt-cli/test/bench/dev.bench.ts b/packages/nuxt-cli/test/bench/dev.bench.ts index 1003906a1..24b979914 100644 --- a/packages/nuxt-cli/test/bench/dev.bench.ts +++ b/packages/nuxt-cli/test/bench/dev.bench.ts @@ -1,4 +1,5 @@ import type { Nuxt } from '@nuxt/schema' +import type { Listener } from 'listhen' import { rm } from 'node:fs/promises' import { join } from 'node:path' @@ -40,6 +41,16 @@ describe('dev', async () => { await (result as { listener: any }).listener.close() }) - // it.skip('makes requests to dev server', async () => { - // }) + bench('makes requests to dev server', async () => { + const { result } = await runCommand('dev', [fixtureDir]) as { result: { listener: Listener } } + const url = result.listener.url + for (let i = 0; i < 10; i++) { + const html = await fetch(url).then(r => r.text()) + if (!html.includes('Welcome to the Nuxt CLI playground!')) { + throw new Error('Unexpected response from dev server') + } + await fetch(`${url}_nuxt/@vite/client`).then(r => r.text()) + } + await result.listener.close() + }) }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 25ce5796a..b4d619533 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -288,7 +288,7 @@ importers: version: 4.1.0-beta.8 devDependencies: '@nuxt/schema': - specifier: ^3.17.5 + specifier: 3.17.5 version: 3.17.5 '@types/node': specifier: ^22.15.29 From 4e7cdf2699290ccde827553e94a1714ae72f92b0 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 4 Jun 2025 16:28:22 +0200 Subject: [PATCH 5/9] chore: add types --- packages/nuxt-cli/test/bench/dev.bench.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/nuxt-cli/test/bench/dev.bench.ts b/packages/nuxt-cli/test/bench/dev.bench.ts index 24b979914..09fc3f910 100644 --- a/packages/nuxt-cli/test/bench/dev.bench.ts +++ b/packages/nuxt-cli/test/bench/dev.bench.ts @@ -23,8 +23,8 @@ describe('dev', async () => { }, }, }, - }) - await (result as { listener: any }).listener.close() + }) as { result: { listener: Listener } } + await result.listener.close() }) bench('starts dev server in no-fork mode', async () => { @@ -37,8 +37,8 @@ describe('dev', async () => { }, }, }, - }) - await (result as { listener: any }).listener.close() + }) as { result: { listener: Listener } } + await result.listener.close() }) bench('makes requests to dev server', async () => { From f8a3ba4e947ee9023b5b42f036d42a93a9519fdf Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 4 Jun 2025 16:28:52 +0200 Subject: [PATCH 6/9] ci: don't run on mac --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e66aa4e4d..b737fad65 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: ci: strategy: matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 From bee63268826a202d61a44d6da29d54b80731d7a2 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 4 Jun 2025 16:30:10 +0200 Subject: [PATCH 7/9] test: version by os --- packages/nuxt-cli/test/bench/dev.bench.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/nuxt-cli/test/bench/dev.bench.ts b/packages/nuxt-cli/test/bench/dev.bench.ts index 09fc3f910..6861afe67 100644 --- a/packages/nuxt-cli/test/bench/dev.bench.ts +++ b/packages/nuxt-cli/test/bench/dev.bench.ts @@ -2,6 +2,7 @@ import type { Nuxt } from '@nuxt/schema' import type { Listener } from 'listhen' import { rm } from 'node:fs/promises' +import os from 'node:os' import { join } from 'node:path' import { fileURLToPath } from 'node:url' @@ -9,7 +10,7 @@ import { bench, describe } from 'vitest' import { runCommand } from '../../../nuxi/src/run' -describe('dev', async () => { +describe(`dev [${os.platform()}]`, async () => { const fixtureDir = fileURLToPath(new URL('../../playground', import.meta.url)) await rm(join(fixtureDir, '.nuxt'), { recursive: true, force: true }) From 1bfb6437e0868c4ca872e84083c4ac29425823d4 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 4 Jun 2025 16:34:19 +0200 Subject: [PATCH 8/9] ci: only run codspeed on linux --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b737fad65..09c0d6fd4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: ci: strategy: matrix: - os: [ubuntu-latest, windows-latest] + os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 @@ -64,6 +64,7 @@ jobs: run: pnpm test:unit - name: Run benchmarks + if: matrix.os == 'ubuntu-latest' uses: CodSpeedHQ/action@0010eb0ca6e89b80c88e8edaaa07cfe5f3e6664d # v3.5.0 with: run: pnpm vitest bench From 1c9a710a59a2a736cdd4c1673a2220851ce0b309 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Wed, 4 Jun 2025 16:47:13 +0200 Subject: [PATCH 9/9] test: setup dev server before request benchmark --- packages/nuxt-cli/test/bench/dev.bench.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/nuxt-cli/test/bench/dev.bench.ts b/packages/nuxt-cli/test/bench/dev.bench.ts index 6861afe67..9fb780d46 100644 --- a/packages/nuxt-cli/test/bench/dev.bench.ts +++ b/packages/nuxt-cli/test/bench/dev.bench.ts @@ -42,16 +42,14 @@ describe(`dev [${os.platform()}]`, async () => { await result.listener.close() }) + const { result } = await runCommand('dev', [fixtureDir]) as { result: { listener: Listener } } + const url = result.listener.url + bench('makes requests to dev server', async () => { - const { result } = await runCommand('dev', [fixtureDir]) as { result: { listener: Listener } } - const url = result.listener.url - for (let i = 0; i < 10; i++) { - const html = await fetch(url).then(r => r.text()) - if (!html.includes('Welcome to the Nuxt CLI playground!')) { - throw new Error('Unexpected response from dev server') - } - await fetch(`${url}_nuxt/@vite/client`).then(r => r.text()) + const html = await fetch(url).then(r => r.text()) + if (!html.includes('Welcome to the Nuxt CLI playground!')) { + throw new Error('Unexpected response from dev server') } - await result.listener.close() - }) + await fetch(`${url}_nuxt/@vite/client`).then(r => r.text()) + }, { time: 10_000 }) })