Skip to content

Commit c21f505

Browse files
feat(perf): update deps (#836)
* feat(perf): swap React for @tanstack/dom-vite shim Drop-in React-compatible shim (~9-10KB gzipped) replacing react / react-dom / react-dom/server via the @tanstack/dom-vite Vite plugin. Installing just @tanstack/dom-vite pulls the full set (dom-core, scheduler, react, react-dom, react-dom-server) transitively. Build-size win: app-shell + react gzip 160KB → 116KB (-44KB). Mobile Lighthouse: slight improvement (-128ms FCP, -27ms TBT). Desktop Lighthouse: parity with baseline. Also: - oxlint: ignore .claude/, disable nested config discovery so stale agent worktrees with their own oxlintrc copies don't break lint. * chore(deps): bump @tanstack/dom-vite to 0.1.0-alpha.3 Brings in raw REACT_LAZY_TYPE child handling in both SSR (walkNode) and client (pushChildren). RSC Flight serializes 'use client' components — CodeBlock, CodeBlockView, CodeExplorer, etc. — as bare lazy objects directly in the tree (not wrapped in REACT_ELEMENT_TYPE). The previous shim dropped those silently, so code snippets disappeared on docs pages (e.g. /virtual/latest/docs/introduction). * feat: bump @tanstack/dom-vite to 0.1.0-alpha.4 + alias runtime-specific server variants Pulls in the shell-chunk batching perf fix landed in the shim's react-dom-server (0.1.0-alpha.4 vs. alpha.3 before). Adds manual top-level aliases for `react-dom/server.{edge,node,bun, browser}` and `react-dom/static.*` → `@tanstack/react-dom-server`. The shim ships a single universal server build; React splits per runtime and @vitejs/plugin-rsc / the Netlify edge adapter import those per-runtime specifiers conditionally. Vite 8's EnvironmentResolveOptions doesn't accept `alias`, so these have to live at top-level resolve.alias. Home route verified rendering cleanly via SSR with no console errors.
1 parent 0e6dc8b commit c21f505

File tree

4 files changed

+80
-2
lines changed

4 files changed

+80
-2
lines changed

.oxlintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
".tanstack-start",
2020
".netlify",
2121
"public",
22-
"convex/.temp"
22+
"convex/.temp",
23+
".claude"
2324
],
2425
"rules": {
2526
"no-array-constructor": "error",

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"build": "vite build",
1313
"start": "vite start",
1414
"start:prod": "pnpm run with-env node scripts/run-built-server.mjs",
15-
"lint": "oxlint --type-aware",
15+
"lint": "oxlint --type-aware --disable-nested-config",
1616
"format": "oxfmt --write",
1717
"db:generate": "drizzle-kit generate",
1818
"db:migrate": "drizzle-kit migrate",
@@ -122,6 +122,7 @@
122122
"@playwright/test": "^1.59.0",
123123
"@shikijs/transformers": "^4.0.2",
124124
"@tanstack/devtools-vite": "^0.6.0",
125+
"@tanstack/dom-vite": "0.1.0-alpha.4",
125126
"@tanstack/react-devtools": "^0.10.2",
126127
"@tanstack/react-query-devtools": "^5.99.0",
127128
"@types/hast": "^3.0.4",

pnpm-lock.yaml

Lines changed: 50 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vite.config.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { sentryTanstackStart } from '@sentry/tanstackstart-react/vite'
22
import { defineConfig } from 'vite'
3+
import { tanstackDom } from '@tanstack/dom-vite'
34
import contentCollections from '@content-collections/vite'
45
import { devtools as tanstackDevtools } from '@tanstack/devtools-vite'
56
import { tanstackStart } from '@tanstack/react-start/plugin/vite'
@@ -36,10 +37,28 @@ const rscSsrExternals = [
3637
const sentrySsrExternals = ['@sentry/node', '@sentry/tanstackstart-react']
3738
const dbSsrExternals = ['drizzle-orm', 'drizzle-orm/postgres-js']
3839

40+
// Runtime-specific `react-dom/server` variants aren't in @tanstack/dom-vite's
41+
// default alias map — our shim ships a single universal server build, unlike
42+
// React which maintains per-runtime forks (edge/node/bun/browser + static.*).
43+
// @vitejs/plugin-rsc and Netlify's edge adapter import them conditionally, so
44+
// we funnel them all to `@tanstack/react-dom-server` at the top-level resolve
45+
// (Vite 8's `EnvironmentResolveOptions` doesn't accept `alias`, so env-scoped
46+
// aliasing isn't an option).
47+
const serverVariantAliases: Record<string, string> = {
48+
'react-dom/server.edge': '@tanstack/react-dom-server',
49+
'react-dom/server.node': '@tanstack/react-dom-server',
50+
'react-dom/server.bun': '@tanstack/react-dom-server',
51+
'react-dom/server.browser': '@tanstack/react-dom-server',
52+
'react-dom/static.edge': '@tanstack/react-dom-server',
53+
'react-dom/static.node': '@tanstack/react-dom-server',
54+
'react-dom/static': '@tanstack/react-dom-server',
55+
}
56+
3957
export default defineConfig({
4058
resolve: {
4159
alias: {
4260
'~': path.resolve(__dirname, './src'),
61+
...serverVariantAliases,
4362
},
4463
},
4564
server: {
@@ -102,6 +121,12 @@ export default defineConfig({
102121
'discord-interactions',
103122
// Don't pre-bundle CLI so we always get fresh changes during dev
104123
...(isDev ? ['@tanstack/cli'] : []),
124+
// `use client` libraries that plugin-rsc pre-bundles inconsistently
125+
// across client/ssr/rsc envs when combined with our React shim — each
126+
// env resolves `react` to a different target, so the optimizer's hash
127+
// diverges. Excluding from optimize keeps resolution deterministic per
128+
// env and silences the 50k+ "inconsistently optimized" warning flood.
129+
'lucide-react',
105130
],
106131
},
107132
build: {
@@ -168,6 +193,7 @@ export default defineConfig({
168193
},
169194
},
170195
plugins: [
196+
tanstackDom(),
171197
...(isDev ? [tanstackDevtools()] : []),
172198
tanstackStart({
173199
rsc: {

0 commit comments

Comments
 (0)