swr — Engineering Performance
3 engineers all time · Feb 2025 – Sep 2026 · built 2026-09-08 · GitHub
Performance snapshot
Today's rolling 90-day reading for swr, compared with the start of the series. Pick a window to move that comparison point.
Avg. perf / dev / mo
+4200.0%
0.01 → 0.29 ETV
Active engineers
+100.0%
1.0 → 2.0
Features
+29.7pp
0.0% → 29.7%
vs. Vercel
0.07x
0.01x → 0.07x · −93% below
swr vs. Vercel
Per-engineer ETV for swr against Vercel as a whole. Both lines are 90-day rolling averages scaled to a 30-day month, so they share one axis and can be read against each other at any point. Pick a window to zoom the chart to it.
Performance Composition
Each month's output split by type of work: Features (new value), Maintenance (sustaining systems), Tests, Docs, and Fixes (rework). The yellow line is output per engineer, so when it rises each engineer is delivering more, whatever the team size did. Unit: Engineering Throughput Value (ETV).
Engineering capacity
Effective engineers behind swr, against its pre-AI baseline. Each subject has its own: swr's is 0.01 ETV / dev / mo, its first reading in May 2025. Per-engineer ETV divided by that gives a capacity multiple, and that multiple applied to the engineers active in the trailing 90 days turns it into engineer-equivalents. The line is the real headcount, so the gap between line and area is what the leverage is worth. Because each baseline is its own, every subject opens at 1.0x on its first day: multiples measure improvement and are not comparable between subjects.
Knowledge concentration
How dependent is this repo on a small number of engineers? Higher top-1 share = higher key-person risk.
Jiachi Liu owns 88.9 % of commits.
Behind the numbers
Written summary of the work completed each month.
No monthly reports available yet.
Most impactful commits
Top 10 by ETV in the all-time window.
- 0.7ETVfeat: rsc fetches and prefill swr cache (#4275) Add RSC cache preloading for SWR. This lets a Server Component call `preload(key, fetcher)` and pass the returned `cacheData` object through the server/client boundary into `SWRConfig`. On the client, `useSWR` consumes that cache data before calling the browser fetcher, returns the server-loaded value, and writes it into the SWR cache after hydration. Flow: ```txt Server Component preload(key, fetcher) | returns { [serializedKey]: dataOrPromise } v Client Boundary <SWRConfig value={{ cacheData }}> | v useSWR(key, clientFetcher) - uses server-loaded cache data for initial data - hydrates the SWR cache after hydration - skips duplicate initial browser fetch/revalidation - later mutate/focus/reconnect revalidation still uses clientFetcher ``` Example: ```tsx // Server Component import { preload } from 'swr' import { ClientRoot } from './client' const key = '/api/user' async function getUser() { return { name: 'Ada' } } export default function Page() { const cacheData = preload(key, getUser) return <ClientRoot cacheData={cacheData} /> } ``` ```tsx // Client Component 'use client' import useSWR, { SWRConfig } from 'swr' import type { CacheData } from 'swr' const key = '/api/user' async function fetchUser() { const res = await fetch(key) return res.json() } function User() { const { data } = useSWR(key, fetchUser) return <div>{data.name}</div> } export function ClientRoot({ cacheData }: { cacheData: CacheData }) { return ( <SWRConfig value={{ cacheData }}> <User /> </SWRConfig> ) } ``` `cacheData` is object-shaped, so nested configs merge like `fallback` and duplicate keys are replaced by the later config. The tests cover Suspense and default modes, prevent leaking the internal cache-data record into user data, and verify that explicit later revalidation still calls the client fetcher. Resolves #4065Jiachi Liu · d2e2f2c0 · 2026-07-02
- 0.6ETVfeat: unload() api (#4298) resolves #4297Jiachi Liu · 723867fd · 2026-07-15
- 0.3ETVfix: react.use should not depend on data condition (#4150)Jiachi Liu · 83761ac2 · 2025-08-05
- 0.2ETVre-organize e2e (#4289) Refine e2e structure, support dev & prod modes, upgrade Next.js to latest canary e2e/site wasn't a workspace package — its deps were never installed and it silently built with the root's Next.js and React 18. It also could only run against a prod build. Now the app lives at t`est/e2e/site` as a real workspace package on next@16.3.0-canary.76 + React 19, and Playwright runs in either mode: ``` pnpm dev:e2e # run the site (localhost:4000) pnpm build:e2e && pnpm test:e2e # test against next start pnpm test:e2e:dev # test against next dev ```Jiachi Liu · 46c9a736 · 2026-07-06
- 0.2ETVPrevent resolved promise to suspend due to missing status (#4271) * test: cover resolved undefined suspense paths * fix: skip empty suspense thenables * refactor: restore non-conditional suspense thenablesJiwon Choi · a89bbe71 · 2026-06-19
- 0.1ETVfix: do not error when not enabled during suspense (#4156)Jiachi Liu · 43207966 · 2025-08-11
- 0.0ETVchore: upgrade to TypeScript 7 (#4305) ## Summary Upgrades the repo to TypeScript 7 (`7.0.2`, the native Go port). Three things in TS 7 broke, each fixed here: - **`.d.ts` generation failed the build outright.** TS 7 no longer ships the JavaScript compiler API, so bunchee errored with `Detected TypeScript 7.0.2, which no longer ships the JavaScript compiler API required for generating type declarations`. Added `@typescript/typescript6` as a devDependency, which supplies that API — bunchee now reports `Using @typescript/typescript6 API for TypeScript 7.0.2 type declaration generation` and emits declarations as before. - **`test/tsconfig.json` failed to load** with `TS5102: Option 'baseUrl' has been removed` and `TS5090: Non-relative paths are not allowed`. The `paths` block it guarded was already dead — it mapped `swr` and friends to `core/src/index.ts`, a layout that no longer exists now that sources live under `src/*` and the top-level directories are `package.json` shims pointing at `dist/`. Tests resolve `swr`/`swr/*` through the `node_modules/swr` → repo-root self-link and its exports map, so removing the block changes nothing (verified by running TS 5.9.3 against both the old and new config). - **`process`, `global`, `require`, and `expect` became `Cannot find name`.** TS 7 no longer auto-includes `@types/node` and `@types/jest` from `typeRoots` for the test projects; `--listFiles` confirmed `@types/node` was never loaded. Declared `types: ["node", "jest"]` explicitly in the two test tsconfigs, which works under both 5.9.3 and 7. The e2e fixture site needed the same treatment. Next.js also `require()`s the TS JavaScript compiler API for its build-time type check, so `next build` failed with `TypeScript 7.0.2 does not provide the compiler API required by Next.js`. Bumped it to `next@16.3.0-canary.97` and enabled `experimental.useTypeScriptCli`, which drives the `tsc` CLI instead. That surfaced two more removed options in the site's tsconfig — `target: es5` (`TS5108`) and `baseUrl` (`TS5102`) — bumped to `es2017` and dropped `baseUrl`, whose `~/*` paths are already relative to the tsconfig directory. ## Notes `rollup-plugin-dts` still declares `typescript@^4.5 || ^5.0 || ^6.0`, so installs print an unmet-peer warning. Declaration generation goes through `@typescript/typescript6` rather than that peer, and `attw --pack .` is green across every entrypoint.Jiachi Liu · 6e68cdce · 2026-07-27
- 0.0ETVci: update release job (#4278)Jiachi Liu · 10b6b65d · 2026-06-22
- 0.0ETVRevert "feat: modify cache type to allow generic usage" (#4151)Jiachi Liu · 31185213 · 2025-07-29
- 0.0ETVchore: use oxfmt and oxlint (#4288)Jiachi Liu · c822a5df · 2026-07-03