From ebb9a4faffddabeaa23c37ac663e8c65b7345310 Mon Sep 17 00:00:00 2001
From: Zack Tanner <1939140+ztanner@users.noreply.github.com>
Date: Tue, 27 Jan 2026 13:09:16 -0800
Subject: [PATCH] switch to cache components
---
apps/next-app/app/api/tweet/[id]/route.ts | 6 +-
apps/next-app/app/light/[tweet]/page.tsx | 23 +++--
.../next-app/app/light/cache/[tweet]/page.tsx | 8 +-
.../app/light/cache/[tweet]/tweet-page.tsx | 19 +++--
.../app/light/suspense/[tweet]/page.tsx | 8 +-
.../app/light/suspense/[tweet]/tweet-page.tsx | 8 +-
.../app/light/vercel-kv/[tweet]/page.tsx | 8 +-
.../light/vercel-kv/[tweet]/tweet-page.tsx | 8 +-
apps/next-app/next.config.mjs | 1 +
apps/next-app/package.json | 2 +-
apps/next-app/tsconfig.json | 3 +-
pnpm-lock.yaml | 83 ++++++++++---------
12 files changed, 108 insertions(+), 69 deletions(-)
diff --git a/apps/next-app/app/api/tweet/[id]/route.ts b/apps/next-app/app/api/tweet/[id]/route.ts
index 993ebf1b..efe945ce 100644
--- a/apps/next-app/app/api/tweet/[id]/route.ts
+++ b/apps/next-app/app/api/tweet/[id]/route.ts
@@ -1,12 +1,14 @@
import { NextResponse } from 'next/server'
import { getTweet } from 'react-tweet/api'
-
-export const fetchCache = 'only-cache'
+import { cacheLife } from 'next/cache'
export async function GET(
_req: Request,
{ params }: RouteContext<'/api/tweet/[id]'>
) {
+ 'use cache'
+ cacheLife('days')
+
try {
const { id } = await params
const tweet = await getTweet(id)
diff --git a/apps/next-app/app/light/[tweet]/page.tsx b/apps/next-app/app/light/[tweet]/page.tsx
index 97e585dd..211abb7c 100644
--- a/apps/next-app/app/light/[tweet]/page.tsx
+++ b/apps/next-app/app/light/[tweet]/page.tsx
@@ -1,15 +1,21 @@
import { Tweet } from 'react-tweet'
import { getTweet } from 'react-tweet/api'
+import { cacheLife } from 'next/cache'
import { components } from './tweet-components'
type Props = {
params: Promise<{ tweet: string }>
}
-export const revalidate = 1800
+export async function generateStaticParams() {
+ return [{ tweet: '1969515038512926823' }]
+}
export async function generateMetadata({ params }: Props) {
- const id = await params.then((p) => p.tweet)
+ 'use cache'
+ cacheLife('hours')
+
+ const { tweet: id } = await params
const tweet = await getTweet(id).catch(() => undefined)
if (!tweet) return { title: 'Next Tweet' }
@@ -24,7 +30,14 @@ export async function generateMetadata({ params }: Props) {
return { title: `${text}${username}` }
}
-export default async function Page({ params }: Props) {
- const id = await params.then((p) => p.tweet)
- return
+async function TweetContent({ params }: Props) {
+ 'use cache'
+ cacheLife('hours')
+
+ const { tweet } = await params
+ return
+}
+
+export default function Page({ params }: Props) {
+ return
}
diff --git a/apps/next-app/app/light/cache/[tweet]/page.tsx b/apps/next-app/app/light/cache/[tweet]/page.tsx
index 951bd701..dbdeabb8 100644
--- a/apps/next-app/app/light/cache/[tweet]/page.tsx
+++ b/apps/next-app/app/light/cache/[tweet]/page.tsx
@@ -2,11 +2,13 @@ import { Suspense } from 'react'
import { TweetSkeleton } from 'react-tweet'
import TweetPage from './tweet-page'
-export const revalidate = 86400
+type Props = {
+ params: Promise<{ tweet: string }>
+}
-const Page = ({ params }: { params: { tweet: string } }) => (
+const Page = ({ params }: Props) => (
}>
-
+
)
diff --git a/apps/next-app/app/light/cache/[tweet]/tweet-page.tsx b/apps/next-app/app/light/cache/[tweet]/tweet-page.tsx
index c3160e85..033d4db6 100644
--- a/apps/next-app/app/light/cache/[tweet]/tweet-page.tsx
+++ b/apps/next-app/app/light/cache/[tweet]/tweet-page.tsx
@@ -1,14 +1,17 @@
-import { unstable_cache } from 'next/cache'
-import { getTweet as _getTweet } from 'react-tweet/api'
+import { cacheLife } from 'next/cache'
+import { getTweet } from 'react-tweet/api'
import { EmbeddedTweet, TweetNotFound } from 'react-tweet'
-const getTweet = unstable_cache(
- async (id: string) => _getTweet(id),
- ['tweet'],
- { revalidate: 3600 * 24 }
-)
+type Props = {
+ params: Promise<{ tweet: string }>
+}
+
+const TweetPage = async ({ params }: Props) => {
+ 'use cache'
+ cacheLife('days')
+
+ const { tweet: id } = await params
-const TweetPage = async ({ id }: { id: string }) => {
try {
const tweet = await getTweet(id)
return tweet ? :
diff --git a/apps/next-app/app/light/suspense/[tweet]/page.tsx b/apps/next-app/app/light/suspense/[tweet]/page.tsx
index 67a1b32d..dbdeabb8 100644
--- a/apps/next-app/app/light/suspense/[tweet]/page.tsx
+++ b/apps/next-app/app/light/suspense/[tweet]/page.tsx
@@ -2,11 +2,13 @@ import { Suspense } from 'react'
import { TweetSkeleton } from 'react-tweet'
import TweetPage from './tweet-page'
-export const revalidate = 3600
+type Props = {
+ params: Promise<{ tweet: string }>
+}
-const Page = ({ params }: { params: { tweet: string } }) => (
+const Page = ({ params }: Props) => (
}>
-
+
)
diff --git a/apps/next-app/app/light/suspense/[tweet]/tweet-page.tsx b/apps/next-app/app/light/suspense/[tweet]/tweet-page.tsx
index 82338785..b79914cf 100644
--- a/apps/next-app/app/light/suspense/[tweet]/tweet-page.tsx
+++ b/apps/next-app/app/light/suspense/[tweet]/tweet-page.tsx
@@ -1,7 +1,13 @@
import { getTweet } from 'react-tweet/api'
import { EmbeddedTweet, TweetNotFound } from 'react-tweet'
-const TweetPage = async ({ id }: { id: string }) => {
+type Props = {
+ params: Promise<{ tweet: string }>
+}
+
+const TweetPage = async ({ params }: Props) => {
+ const { tweet: id } = await params
+
try {
const tweet = await getTweet(id)
return tweet ? :
diff --git a/apps/next-app/app/light/vercel-kv/[tweet]/page.tsx b/apps/next-app/app/light/vercel-kv/[tweet]/page.tsx
index 951bd701..dbdeabb8 100644
--- a/apps/next-app/app/light/vercel-kv/[tweet]/page.tsx
+++ b/apps/next-app/app/light/vercel-kv/[tweet]/page.tsx
@@ -2,11 +2,13 @@ import { Suspense } from 'react'
import { TweetSkeleton } from 'react-tweet'
import TweetPage from './tweet-page'
-export const revalidate = 86400
+type Props = {
+ params: Promise<{ tweet: string }>
+}
-const Page = ({ params }: { params: { tweet: string } }) => (
+const Page = ({ params }: Props) => (
}>
-
+
)
diff --git a/apps/next-app/app/light/vercel-kv/[tweet]/tweet-page.tsx b/apps/next-app/app/light/vercel-kv/[tweet]/tweet-page.tsx
index fdf944f7..d5c9eeac 100644
--- a/apps/next-app/app/light/vercel-kv/[tweet]/tweet-page.tsx
+++ b/apps/next-app/app/light/vercel-kv/[tweet]/tweet-page.tsx
@@ -2,6 +2,10 @@ import { fetchTweet, Tweet } from 'react-tweet/api'
import { EmbeddedTweet, TweetNotFound } from 'react-tweet'
import { kv } from '@vercel/kv'
+type Props = {
+ params: Promise<{ tweet: string }>
+}
+
async function getTweet(
id: string,
fetchOptions?: RequestInit
@@ -25,7 +29,9 @@ async function getTweet(
return cachedTweet ?? undefined
}
-const TweetPage = async ({ id }: { id: string }) => {
+const TweetPage = async ({ params }: Props) => {
+ const { tweet: id } = await params
+
try {
const tweet = await getTweet(id)
return tweet ? :
diff --git a/apps/next-app/next.config.mjs b/apps/next-app/next.config.mjs
index 38519916..7af131d1 100644
--- a/apps/next-app/next.config.mjs
+++ b/apps/next-app/next.config.mjs
@@ -4,6 +4,7 @@ const withMDX = mdx()
/** @type {import('next').NextConfig} */
const nextConfig = {
+ cacheComponents: true,
pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'],
images: {
remotePatterns: [
diff --git a/apps/next-app/package.json b/apps/next-app/package.json
index f85a018d..b44de4ae 100644
--- a/apps/next-app/package.json
+++ b/apps/next-app/package.json
@@ -15,7 +15,7 @@
"@next/mdx": "^15.5.3",
"@vercel/kv": "^3.0.0",
"clsx": "^2.1.1",
- "next": "15.6.0-canary.59",
+ "next": "latest",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"react-tweet": "workspace:*"
diff --git a/apps/next-app/tsconfig.json b/apps/next-app/tsconfig.json
index 476c62cb..609ae051 100644
--- a/apps/next-app/tsconfig.json
+++ b/apps/next-app/tsconfig.json
@@ -29,7 +29,8 @@
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
- ".next/types/**/*.ts"
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts"
],
"exclude": [
"node_modules"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9e2dcaa3..e5180183 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -91,8 +91,8 @@ importers:
specifier: ^2.1.1
version: 2.1.1
next:
- specifier: 15.6.0-canary.59
- version: 15.6.0-canary.59(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
+ specifier: latest
+ version: 16.1.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
react:
specifier: ^19.1.1
version: 19.1.1
@@ -953,8 +953,8 @@ packages:
'@next/env@15.5.8':
resolution: {integrity: sha512-ejZHa3ogTxcy851dFoNtfB5B2h7AbSAtHbR5CymUlnz4yW1QjHNufVpvTu8PTnWBKFKjrd4k6Gbi2SsCiJKvxw==}
- '@next/env@15.6.0-canary.59':
- resolution: {integrity: sha512-D5msVvBiiJrqAW3MPXP4rR7teMeCcMLCK3yTSCGM4XuuzAcO8Eb4RZtbSPS0zgvFKu9r5hv5eaTXlNmgNmZ5TQ==}
+ '@next/env@16.1.5':
+ resolution: {integrity: sha512-CRSCPJiSZoi4Pn69RYBDI9R7YK2g59vLexPQFXY0eyw+ILevIenCywzg+DqmlBik9zszEnw2HLFOUlLAcJbL7g==}
'@next/eslint-plugin-next@14.2.32':
resolution: {integrity: sha512-tyZMX8g4cWg/uPW4NxiJK13t62Pab47SKGJGVZJa6YtFwtfrXovH4j1n9tdpRdXW03PGQBugYEVGM7OhWfytdA==}
@@ -985,8 +985,8 @@ packages:
cpu: [arm64]
os: [darwin]
- '@next/swc-darwin-arm64@15.6.0-canary.58':
- resolution: {integrity: sha512-jGawwiKITJHOH8dSbTqfjVvCf+DesljZhtvh9LKCrO+1octLlGyDAbEQw5WEzrXCch5LWrdSqPyKft0/9LeniA==}
+ '@next/swc-darwin-arm64@16.1.5':
+ resolution: {integrity: sha512-eK7Wdm3Hjy/SCL7TevlH0C9chrpeOYWx2iR7guJDaz4zEQKWcS1IMVfMb9UKBFMg1XgzcPTYPIp1Vcpukkjg6Q==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
@@ -1003,8 +1003,8 @@ packages:
cpu: [x64]
os: [darwin]
- '@next/swc-darwin-x64@15.6.0-canary.58':
- resolution: {integrity: sha512-iD15Eav7Y7lQOCFvsPf9NMwo3dFrHZMX4wghrEysLuwOEJC9zM0jOSb1hdSqZwf1Odn86CIiJUvXH1UcfAm6og==}
+ '@next/swc-darwin-x64@16.1.5':
+ resolution: {integrity: sha512-foQscSHD1dCuxBmGkbIr6ScAUF6pRoDZP6czajyvmXPAOFNnQUJu2Os1SGELODjKp/ULa4fulnBWoHV3XdPLfA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
@@ -1021,8 +1021,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@next/swc-linux-arm64-gnu@15.6.0-canary.58':
- resolution: {integrity: sha512-b8ayBG/wrycIilOFP/zU6yPQI8UVMtrQfowNaoCvG7FIuu5Fpa7MwPEGWXPyvwn2qQM5fDSsVGQOrjQ6gWLTbA==}
+ '@next/swc-linux-arm64-gnu@16.1.5':
+ resolution: {integrity: sha512-qNIb42o3C02ccIeSeKjacF3HXotGsxh/FMk/rSRmCzOVMtoWH88odn2uZqF8RLsSUWHcAqTgYmPD3pZ03L9ZAA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@@ -1039,8 +1039,8 @@ packages:
cpu: [arm64]
os: [linux]
- '@next/swc-linux-arm64-musl@15.6.0-canary.58':
- resolution: {integrity: sha512-KMYPUdBTAITdgxRNjMKdG85bHsn3wu0KWPV2nftoov2/dVs5eFJ47w+m4upPdTgBXRAHY50OvS/nzf5mN/TXeQ==}
+ '@next/swc-linux-arm64-musl@16.1.5':
+ resolution: {integrity: sha512-U+kBxGUY1xMAzDTXmuVMfhaWUZQAwzRaHJ/I6ihtR5SbTVUEaDRiEU9YMjy1obBWpdOBuk1bcm+tsmifYSygfw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@@ -1057,8 +1057,8 @@ packages:
cpu: [x64]
os: [linux]
- '@next/swc-linux-x64-gnu@15.6.0-canary.58':
- resolution: {integrity: sha512-myknT/if7wuwss0B/1Le7ymlN0Zr/DsfGji8b+XcqeFhoy1GxQerfTlrsblZTB6EIPIex1QPRUbpIcy+N9Qfpw==}
+ '@next/swc-linux-x64-gnu@16.1.5':
+ resolution: {integrity: sha512-gq2UtoCpN7Ke/7tKaU7i/1L7eFLfhMbXjNghSv0MVGF1dmuoaPeEVDvkDuO/9LVa44h5gqpWeJ4mRRznjDv7LA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@@ -1075,8 +1075,8 @@ packages:
cpu: [x64]
os: [linux]
- '@next/swc-linux-x64-musl@15.6.0-canary.58':
- resolution: {integrity: sha512-3A1YLtmuot0pnZqDHV2iAfUrvQS0zp7xXUlqNb8flAJAu1Civ+2qt94l0kTfUjWHtFFUENyt2yEcXEqxuxEJfg==}
+ '@next/swc-linux-x64-musl@16.1.5':
+ resolution: {integrity: sha512-bQWSE729PbXT6mMklWLf8dotislPle2L70E9q6iwETYEOt092GDn0c+TTNj26AjmeceSsC4ndyGsK5nKqHYXjQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@@ -1093,8 +1093,8 @@ packages:
cpu: [arm64]
os: [win32]
- '@next/swc-win32-arm64-msvc@15.6.0-canary.58':
- resolution: {integrity: sha512-3hkMBi/Zbatqi9vwnh1zuOWQerS4CtUptn9cj4NRtVAJurzhfQBwz8RJIq/5f85XDkq0LxDrhyABZ+6RU7Un7Q==}
+ '@next/swc-win32-arm64-msvc@16.1.5':
+ resolution: {integrity: sha512-LZli0anutkIllMtTAWZlDqdfvjWX/ch8AFK5WgkNTvaqwlouiD1oHM+WW8RXMiL0+vAkAJyAGEzPPjO+hnrSNQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
@@ -1117,8 +1117,8 @@ packages:
cpu: [x64]
os: [win32]
- '@next/swc-win32-x64-msvc@15.6.0-canary.58':
- resolution: {integrity: sha512-CFB6BzqgYJ7yJvoji0KD5nWf88JN5/iliiLn/kfzxUMvfaKmoYLrGZwRuePrAwLdBpczEsgcmuER6YuT9/pZLw==}
+ '@next/swc-win32-x64-msvc@16.1.5':
+ resolution: {integrity: sha512-7is37HJTNQGhjPpQbkKjKEboHYQnCgpVt/4rBrrln0D9nderNxZ8ZWs8w1fAtzUx7wEyYjQ+/13myFgFj6K2Ng==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -3830,8 +3830,8 @@ packages:
sass:
optional: true
- next@15.6.0-canary.59:
- resolution: {integrity: sha512-FOKHnHEVqtbMj2eQfgRgEkzEds/hqjz5JRBjLhT7UgPtvs36Vzc7RU9mh8lOZt/TONS7jVs+5ilv194QA/wdnQ==}
+ next@16.1.5:
+ resolution: {integrity: sha512-f+wE+NSbiQgh3DSAlTaw2FwY5yGdVViAtp8TotNQj4kk4Q8Bh1sC/aL9aH+Rg1YAVn18OYXsRDT7U/079jgP7w==}
engines: {node: '>=20.9.0'}
hasBin: true
peerDependencies:
@@ -5853,7 +5853,7 @@ snapshots:
'@next/env@15.5.8': {}
- '@next/env@15.6.0-canary.59': {}
+ '@next/env@16.1.5': {}
'@next/eslint-plugin-next@14.2.32':
dependencies:
@@ -5875,7 +5875,7 @@ snapshots:
'@next/swc-darwin-arm64@15.5.7':
optional: true
- '@next/swc-darwin-arm64@15.6.0-canary.58':
+ '@next/swc-darwin-arm64@16.1.5':
optional: true
'@next/swc-darwin-x64@14.2.33':
@@ -5884,7 +5884,7 @@ snapshots:
'@next/swc-darwin-x64@15.5.7':
optional: true
- '@next/swc-darwin-x64@15.6.0-canary.58':
+ '@next/swc-darwin-x64@16.1.5':
optional: true
'@next/swc-linux-arm64-gnu@14.2.33':
@@ -5893,7 +5893,7 @@ snapshots:
'@next/swc-linux-arm64-gnu@15.5.7':
optional: true
- '@next/swc-linux-arm64-gnu@15.6.0-canary.58':
+ '@next/swc-linux-arm64-gnu@16.1.5':
optional: true
'@next/swc-linux-arm64-musl@14.2.33':
@@ -5902,7 +5902,7 @@ snapshots:
'@next/swc-linux-arm64-musl@15.5.7':
optional: true
- '@next/swc-linux-arm64-musl@15.6.0-canary.58':
+ '@next/swc-linux-arm64-musl@16.1.5':
optional: true
'@next/swc-linux-x64-gnu@14.2.33':
@@ -5911,7 +5911,7 @@ snapshots:
'@next/swc-linux-x64-gnu@15.5.7':
optional: true
- '@next/swc-linux-x64-gnu@15.6.0-canary.58':
+ '@next/swc-linux-x64-gnu@16.1.5':
optional: true
'@next/swc-linux-x64-musl@14.2.33':
@@ -5920,7 +5920,7 @@ snapshots:
'@next/swc-linux-x64-musl@15.5.7':
optional: true
- '@next/swc-linux-x64-musl@15.6.0-canary.58':
+ '@next/swc-linux-x64-musl@16.1.5':
optional: true
'@next/swc-win32-arm64-msvc@14.2.33':
@@ -5929,7 +5929,7 @@ snapshots:
'@next/swc-win32-arm64-msvc@15.5.7':
optional: true
- '@next/swc-win32-arm64-msvc@15.6.0-canary.58':
+ '@next/swc-win32-arm64-msvc@16.1.5':
optional: true
'@next/swc-win32-ia32-msvc@14.2.33':
@@ -5941,7 +5941,7 @@ snapshots:
'@next/swc-win32-x64-msvc@15.5.7':
optional: true
- '@next/swc-win32-x64-msvc@15.6.0-canary.58':
+ '@next/swc-win32-x64-msvc@16.1.5':
optional: true
'@nodelib/fs.scandir@2.1.5':
@@ -9354,24 +9354,25 @@ snapshots:
- '@babel/core'
- babel-plugin-macros
- next@15.6.0-canary.59(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
+ next@16.1.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1):
dependencies:
- '@next/env': 15.6.0-canary.59
+ '@next/env': 16.1.5
'@swc/helpers': 0.5.15
+ baseline-browser-mapping: 2.8.6
caniuse-lite: 1.0.30001743
postcss: 8.4.31
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
styled-jsx: 5.1.6(react@19.1.1)
optionalDependencies:
- '@next/swc-darwin-arm64': 15.6.0-canary.58
- '@next/swc-darwin-x64': 15.6.0-canary.58
- '@next/swc-linux-arm64-gnu': 15.6.0-canary.58
- '@next/swc-linux-arm64-musl': 15.6.0-canary.58
- '@next/swc-linux-x64-gnu': 15.6.0-canary.58
- '@next/swc-linux-x64-musl': 15.6.0-canary.58
- '@next/swc-win32-arm64-msvc': 15.6.0-canary.58
- '@next/swc-win32-x64-msvc': 15.6.0-canary.58
+ '@next/swc-darwin-arm64': 16.1.5
+ '@next/swc-darwin-x64': 16.1.5
+ '@next/swc-linux-arm64-gnu': 16.1.5
+ '@next/swc-linux-arm64-musl': 16.1.5
+ '@next/swc-linux-x64-gnu': 16.1.5
+ '@next/swc-linux-x64-musl': 16.1.5
+ '@next/swc-win32-arm64-msvc': 16.1.5
+ '@next/swc-win32-x64-msvc': 16.1.5
sharp: 0.34.4
transitivePeerDependencies:
- '@babel/core'