diff --git a/packages/docs/src/components/BuildInstallStatsTable.astro b/packages/docs/src/components/BuildInstallStatsTable.astro index 1841f5e..d506507 100644 --- a/packages/docs/src/components/BuildInstallStatsTable.astro +++ b/packages/docs/src/components/BuildInstallStatsTable.astro @@ -7,6 +7,7 @@ const buildInstallColumns = [ { key: 'name', header: 'Framework', + nameCell: true, href: (row: Record) => `/framework/${getFrameworkSlug(row.package as string)}`, }, diff --git a/packages/docs/src/components/DependencyStatsTable.astro b/packages/docs/src/components/DependencyStatsTable.astro index 44d26ca..d021036 100644 --- a/packages/docs/src/components/DependencyStatsTable.astro +++ b/packages/docs/src/components/DependencyStatsTable.astro @@ -7,6 +7,7 @@ const depsColumns = [ { key: 'name', header: 'Framework', + nameCell: true, href: (row: Record) => `/framework/${getFrameworkSlug(row.package as string)}`, }, diff --git a/packages/docs/src/components/FrameworkDetail.astro b/packages/docs/src/components/FrameworkDetail.astro deleted file mode 100644 index 87f6ac6..0000000 --- a/packages/docs/src/components/FrameworkDetail.astro +++ /dev/null @@ -1,341 +0,0 @@ ---- -import type { CollectionEntry } from 'astro:content' -import { formatBytesToMB, formatTimeMs } from '../lib/utils' -import '../styles/shared.css' -import BackLink from './BackLink.astro' -import DevTimeChart from './DevTimeChart.astro' -import MethodologyTag from './MethodologyTag.astro' -import PageHeader from './PageHeader.astro' -import SSRStatsMethodologyNotes from './SSRStatsMethodologyNotes.astro' - -interface Props { - devtime: CollectionEntry<'devtime'>['data'] - runtime?: CollectionEntry<'runtime'>['data'] - baseline?: CollectionEntry<'runtime'>['data'] -} - -const { devtime, runtime, baseline } = Astro.props - -const measuredDateDisplay = (() => { - const d = new Date(devtime.timingMeasuredAt) - return Number.isNaN(d.getTime()) - ? devtime.timingMeasuredAt - : d.toLocaleDateString('en-US') -})() ---- - -
- - -
- {devtime.name} - { - (devtime.frameworkVersion ?? devtime.timingMeasuredAt) && ( -

- {devtime.frameworkVersion && ( - Version {devtime.frameworkVersion} - )} - {devtime.frameworkVersion && devtime.timingMeasuredAt && ' · '} - {devtime.timingMeasuredAt && ( - Measured {measuredDateDisplay} - )} -

- ) - } -
- -
-

Dev Time Performance

- - Measured using pnpm on GitHub Actions (ubuntu-latest, Node 24) based on - the starter project set up by each framework's CLI. - - -
- - - - - - - - - - - - - - - - - - - -
Prod DepsDev DepsSizeSize (Prod Only)Graph
{devtime.prodDependencies}{devtime.devDependencies}{formatBytesToMB(devtime.nodeModulesSize)}{formatBytesToMB(devtime.nodeModulesSizeProdOnly)} - - View - -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
MetricAvgMinMax
Install{formatTimeMs(devtime.installTime.avgMs)}{formatTimeMs(devtime.installTime.minMs)}{formatTimeMs(devtime.installTime.maxMs)}
Cold Build{formatTimeMs(devtime.coldBuildTime.avgMs)}{formatTimeMs(devtime.coldBuildTime.minMs)}{formatTimeMs(devtime.coldBuildTime.maxMs)}
Warm Build{formatTimeMs(devtime.warmBuildTime.avgMs)}{formatTimeMs(devtime.warmBuildTime.minMs)}{formatTimeMs(devtime.warmBuildTime.maxMs)}
-
- - - -

- Build output size: - {formatBytesToMB(devtime.buildOutputSize)} -

-
- - { - runtime && ( -
-

Runtime Performance

-

SSR Performance

- - Measured on GitHub Actions (ubuntu-latest, Node 24) using custom SSR - benchmark apps. - -
- - - - - - - - - - - - {baseline && ( - - - - - - - - )} - - - - - - - - -
FrameworkOps/secAvg LatencyBody SizeDuplication
{baseline.name}{baseline.ssrOpsPerSec?.toLocaleString()}{baseline.ssrAvgLatencyMs}ms{baseline.ssrBodySizeKb}kb{baseline.ssrDuplicationFactor}x
{runtime.name}{runtime.ssrOpsPerSec?.toLocaleString()}{runtime.ssrAvgLatencyMs}ms{runtime.ssrBodySizeKb}kb{runtime.ssrDuplicationFactor}x
-
- -
- ) - } -
- - diff --git a/packages/docs/src/components/SSRStatsTable.astro b/packages/docs/src/components/SSRStatsTable.astro index 895c9d2..c89abb4 100644 --- a/packages/docs/src/components/SSRStatsTable.astro +++ b/packages/docs/src/components/SSRStatsTable.astro @@ -8,6 +8,7 @@ const columns = [ { key: 'name', header: 'Framework', + nameCell: true, href: (row: Record) => row.package !== 'app-baseline-html' ? `/framework/${getFrameworkSlug(row.package as string)}` diff --git a/packages/docs/src/components/StatsTable.astro b/packages/docs/src/components/StatsTable.astro index 2fbbfe0..78f62dd 100644 --- a/packages/docs/src/components/StatsTable.astro +++ b/packages/docs/src/components/StatsTable.astro @@ -4,6 +4,7 @@ type Row = Record interface Column { key: string header: string + nameCell?: boolean href?: (row: Row) => string | null | undefined } @@ -20,17 +21,23 @@ const { label, columns, data } = Astro.props - {columns.map((col) => )} + { + columns.map((col) => ( + + )) + } { data.map((row) => ( - {columns.map((col, i) => { + {columns.map((col) => { const href = col.href?.(row) return ( -
{col.header} + {col.header} +
+ {href ? ( {String(row[col.key] ?? '')} @@ -78,7 +85,7 @@ const { label, columns, data } = Astro.props letter-spacing: 0.05em; } - th:not(:first-child) { + th:not(.name-cell) { text-align: center; } diff --git a/packages/docs/src/lib/collections.ts b/packages/docs/src/lib/collections.ts index e3197d0..f604032 100644 --- a/packages/docs/src/lib/collections.ts +++ b/packages/docs/src/lib/collections.ts @@ -31,7 +31,11 @@ const buildInstallData = starterStats.map((f) => ({ minInstall: formatTimeMs(f.installTime.minMs), maxInstall: formatTimeMs(f.installTime.maxMs), avgColdBuild: formatTimeMs(f.coldBuildTime.avgMs), + minColdBuild: formatTimeMs(f.coldBuildTime.minMs), + maxColdBuild: formatTimeMs(f.coldBuildTime.maxMs), avgWarmBuild: formatTimeMs(f.warmBuildTime.avgMs), + minWarmBuild: formatTimeMs(f.warmBuildTime.minMs), + maxWarmBuild: formatTimeMs(f.warmBuildTime.maxMs), buildOutput: formatBytesToMB(f.buildOutputSize), })) diff --git a/packages/docs/src/pages/framework/[slug].astro b/packages/docs/src/pages/framework/[slug].astro index 9b3b385..7535f66 100644 --- a/packages/docs/src/pages/framework/[slug].astro +++ b/packages/docs/src/pages/framework/[slug].astro @@ -1,7 +1,13 @@ --- import { getCollection } from 'astro:content' -import FrameworkDetail from '../../components/FrameworkDetail.astro' +import BackLink from '../../components/BackLink.astro' +import DevTimeChart from '../../components/DevTimeChart.astro' +import MethodologyTag from '../../components/MethodologyTag.astro' +import PageHeader from '../../components/PageHeader.astro' +import SSRStatsMethodologyNotes from '../../components/SSRStatsMethodologyNotes.astro' +import StatsTable from '../../components/StatsTable.astro' import Layout from '../../layouts/Layout.astro' +import { buildInstallData, depsStats } from '../../lib/collections' import { getFrameworkSlug } from '../../lib/utils' export async function getStaticPaths() { @@ -28,10 +34,170 @@ export async function getStaticPaths() { } const { devtime, runtime, baseline } = Astro.props + +const measuredDateDisplay = (() => { + const d = new Date(devtime.timingMeasuredAt) + return Number.isNaN(d.getTime()) + ? devtime.timingMeasuredAt + : d.toLocaleDateString('en-US') +})() + +const depsEntry = depsStats.find((e) => e.package === devtime.package)! +const buildEntry = buildInstallData.find((e) => e.package === devtime.package)! + +const depsColumns = [ + { key: 'prodDependencies', header: 'Prod Deps' }, + { key: 'devDependencies', header: 'Dev Deps' }, + { key: 'nodeModulesSize', header: 'Size' }, + { key: 'nodeModulesSizeProdOnly', header: 'Size (Prod Only)' }, + { + key: 'graph', + header: 'Graph', + href: (row: Record) => row.graphHref as string, + }, +] + +const depsData = [ + { + prodDependencies: String(depsEntry.prodDependencies), + devDependencies: String(depsEntry.devDependencies), + nodeModulesSize: depsEntry.nodeModulesSize, + nodeModulesSizeProdOnly: depsEntry.nodeModulesSizeProdOnly, + graph: depsEntry.graph, + graphHref: `https://npmgraph.js.org/?q=https://github.com/e18e/framework-tracker/blob/main/packages/${devtime.package}/package.json`, + }, +] + +const buildColumns = [ + { key: 'metric', header: 'Metric', nameCell: true }, + { key: 'avg', header: 'Avg' }, + { key: 'min', header: 'Min' }, + { key: 'max', header: 'Max' }, +] + +const buildData = [ + { + metric: 'Install', + avg: buildEntry.avgInstall, + min: buildEntry.minInstall, + max: buildEntry.maxInstall, + }, + { + metric: 'Cold Build', + avg: buildEntry.avgColdBuild, + min: buildEntry.minColdBuild, + max: buildEntry.maxColdBuild, + }, + { + metric: 'Warm Build', + avg: buildEntry.avgWarmBuild, + min: buildEntry.minWarmBuild, + max: buildEntry.maxWarmBuild, + }, +] + +const ssrColumns = [ + { key: 'name', header: 'Framework', nameCell: true }, + { key: 'ssrOpsPerSec', header: 'Ops/sec' }, + { key: 'ssrAvgLatencyMs', header: 'Avg Latency' }, + { key: 'ssrBodySizeKb', header: 'Body Size' }, + { key: 'ssrDuplicationFactor', header: 'Duplication' }, +] + +const ssrData = [ + ...(baseline + ? [ + { + name: baseline.name, + ssrOpsPerSec: baseline.ssrOpsPerSec?.toLocaleString() ?? '', + ssrAvgLatencyMs: `${baseline.ssrAvgLatencyMs}ms`, + ssrBodySizeKb: `${baseline.ssrBodySizeKb}kb`, + ssrDuplicationFactor: `${baseline.ssrDuplicationFactor}x`, + }, + ] + : []), + ...(runtime + ? [ + { + name: runtime.name, + ssrOpsPerSec: runtime.ssrOpsPerSec?.toLocaleString() ?? '', + ssrAvgLatencyMs: `${runtime.ssrAvgLatencyMs}ms`, + ssrBodySizeKb: `${runtime.ssrBodySizeKb}kb`, + ssrDuplicationFactor: `${runtime.ssrDuplicationFactor}x`, + }, + ] + : []), +] --- -
- -
+ +
+ {devtime.name} + { + (devtime.frameworkVersion ?? devtime.timingMeasuredAt) && ( +

+ {devtime.frameworkVersion && ( + Version {devtime.frameworkVersion} + )} + {devtime.frameworkVersion && devtime.timingMeasuredAt && ' · '} + {devtime.timingMeasuredAt && ( + Measured {measuredDateDisplay} + )} +

+ ) + } +
+ +

Dev Time Performance

+ + Measured using pnpm on GitHub Actions (ubuntu-latest, Node 24) based on the + starter project set up by each framework's CLI. + + + + +

+ Build output size: + {buildEntry.buildOutput} +

+ + { + runtime && ( + <> +

Runtime Performance

+

SSR Performance

+ + Measured on GitHub Actions (ubuntu-latest, Node 24) using custom SSR + benchmark apps. + + + + + ) + }
+ + diff --git a/packages/docs/src/styles/shared.css b/packages/docs/src/styles/shared.css index a7a4346..ec6cc30 100644 --- a/packages/docs/src/styles/shared.css +++ b/packages/docs/src/styles/shared.css @@ -1,6 +1,6 @@ /** - * Shared design tokens for framework tracker tables and detail pages. - * Import this in components that render framework stats (e.g. DependencyStats, FrameworkDetail). + * Shared design tokens for framework tracker tables and pages. + * Imported globally via Layout.astro. */ :root {