mirror of
https://github.com/vercel/next.js.git
synced 2026-09-20 02:25:18 +08:00
57a8476086
After each `next experimental-analyze` run, snapshot the output data into a rolling `history/` directory so later builds can use it as a comparison baseline. Each snapshot gets a `metadata.json` with git branch/sha/dirty status, Next.js version, and route count. A `history/history.json` index (newest-first, capped at 20 entries) lets the UI list available baselines without re-reading every snapshot directory. Old snapshots beyond the cap are pruned automatically. The client-side `SnapshotMetadata` type mirror lives in `apps/bundle-analyzer/lib/snapshot.ts` so the compare UI can reference it without a build-time dependency on the Next.js package. <!-- NEXT_JS_LLM_PR --> --------- Co-authored-by: vercel-fleet-prod[bot] <318278635+vercel-fleet-prod[bot]@users.noreply.github.com> Co-authored-by: Will Binns-Smith <755844+wbinnssmith@users.noreply.github.com>
66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
/**
|
|
* Mirrors {@link SnapshotMetadata} written by the build (see
|
|
* `packages/next/src/build/analyze/snapshot.ts`). Field semantics must stay in
|
|
* sync.
|
|
*/
|
|
export interface SnapshotMetadata {
|
|
id: string
|
|
createdAt: string
|
|
nextVersion?: string
|
|
gitBranch?: string
|
|
gitSha?: string
|
|
gitShortSha?: string
|
|
gitDirty?: boolean
|
|
/** First line of the HEAD commit message when available. */
|
|
gitMessage?: string
|
|
appDirOnly?: boolean
|
|
noMangling?: boolean
|
|
/** User-supplied baseline name, overriding branch/sha in display. See `--baseline-name`. */
|
|
baselineName?: string
|
|
routeCount: number
|
|
}
|
|
|
|
/** Mirrors {@link HistoryIndex}. */
|
|
export interface HistoryIndex {
|
|
snapshots: SnapshotMetadata[]
|
|
}
|
|
|
|
/**
|
|
* Returns a short, human-friendly label for a snapshot. Used by the picker
|
|
* and the diff header bar. Format prefers branch + short sha, falling back to
|
|
* timestamp when neither is available.
|
|
*/
|
|
export function formatSnapshotLabel(metadata: SnapshotMetadata): string {
|
|
if (metadata.baselineName) return metadata.baselineName
|
|
const sha = metadata.gitShortSha ? metadata.gitShortSha : null
|
|
const branch = metadata.gitBranch ?? null
|
|
if (branch && sha)
|
|
return `${branch}@${sha}${metadata.gitDirty ? ' (dirty)' : ''}`
|
|
if (sha) return `${sha}${metadata.gitDirty ? ' (dirty)' : ''}`
|
|
if (branch) return branch
|
|
return formatRelativeTime(metadata.createdAt)
|
|
}
|
|
|
|
/**
|
|
* Returns a relative time string for an ISO timestamp ("3m ago", "2h ago",
|
|
* "yesterday", "Jan 4"). Designed for compact list rows.
|
|
*/
|
|
export function formatRelativeTime(iso: string): string {
|
|
const then = new Date(iso).getTime()
|
|
if (Number.isNaN(then)) return iso
|
|
const diffMs = Date.now() - then
|
|
const seconds = Math.round(diffMs / 1000)
|
|
if (seconds < 60) return 'just now'
|
|
const minutes = Math.round(seconds / 60)
|
|
if (minutes < 60) return `${minutes}m ago`
|
|
const hours = Math.round(minutes / 60)
|
|
if (hours < 24) return `${hours}h ago`
|
|
const days = Math.round(hours / 24)
|
|
if (days === 1) return 'yesterday'
|
|
if (days < 14) return `${days}d ago`
|
|
return new Date(iso).toLocaleDateString(undefined, {
|
|
month: 'short',
|
|
day: 'numeric',
|
|
})
|
|
}
|