@pokoblog/next 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -0
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -142,6 +142,88 @@ export async function generateStaticParams() {
|
|
|
142
142
|
published while it runs lands in front of the walk and arrives on the next
|
|
143
143
|
build.
|
|
144
144
|
|
|
145
|
+
## If you turn on Cache Components
|
|
146
|
+
|
|
147
|
+
`cacheComponents: true` is opt-in in Next 16, and the examples above **do not
|
|
148
|
+
build** with it on. It is not a subtle failure — `next build` stops:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
Error: Route "/blog/[slug]": Next.js encountered uncached or runtime data
|
|
152
|
+
during prerendering.
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Two things cause it, and neither is the `fetch` caching being wrong. Under Cache
|
|
156
|
+
Components only `use cache` counts as cached for prerendering; the Data Cache
|
|
157
|
+
this package uses still caches, but it does not satisfy the prerender check. And
|
|
158
|
+
`await params` in a dynamic route is itself runtime data.
|
|
159
|
+
|
|
160
|
+
So: wrap the data access, and give the route its params.
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
// app/blog/page.tsx
|
|
164
|
+
import { cacheLife, cacheTag } from "next/cache";
|
|
165
|
+
import { ArticleList } from "@pokoblog/next";
|
|
166
|
+
|
|
167
|
+
import { poko } from "@/lib/pokoblog";
|
|
168
|
+
|
|
169
|
+
async function CachedList() {
|
|
170
|
+
"use cache";
|
|
171
|
+
cacheLife("minutes");
|
|
172
|
+
cacheTag("pokoblog");
|
|
173
|
+
|
|
174
|
+
return <ArticleList client={poko} limit={20} />;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export default function BlogIndex() {
|
|
178
|
+
return <CachedList />;
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
// app/blog/[slug]/page.tsx — the parts that change
|
|
184
|
+
async function getArticle(slug: string) {
|
|
185
|
+
"use cache";
|
|
186
|
+
cacheLife("minutes");
|
|
187
|
+
cacheTag("pokoblog", `pokoblog:${slug}`);
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
return await poko.article(slug);
|
|
191
|
+
} catch (failure) {
|
|
192
|
+
if (failure instanceof PokoBlogNotFoundError) return null;
|
|
193
|
+
|
|
194
|
+
throw failure;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export async function generateStaticParams() {
|
|
199
|
+
return (await poko.slugs()).map((slug) => ({ slug }));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export default async function ArticlePage({ params }: Props) {
|
|
203
|
+
const { slug } = await params;
|
|
204
|
+
const article = await getArticle(slug);
|
|
205
|
+
|
|
206
|
+
if (!article) notFound();
|
|
207
|
+
|
|
208
|
+
return <ArticleView article={article} />;
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
`notFound()` moves **outside** the cached function, which is why `getArticle`
|
|
213
|
+
returns `null` rather than throwing: `notFound()` works by throwing, and a
|
|
214
|
+
cached scope is the wrong place to do that.
|
|
215
|
+
|
|
216
|
+
`generateMetadata` calls the same `getArticle`, so the article is fetched once
|
|
217
|
+
for both. That is not only tidier — under Cache Components, uncached data in
|
|
218
|
+
`generateMetadata` is an error of its own.
|
|
219
|
+
|
|
220
|
+
Worth the trade: every article then prerenders as static HTML rather than being
|
|
221
|
+
generated on the first request, which is what you want for pages whose audience
|
|
222
|
+
is crawlers.
|
|
223
|
+
|
|
224
|
+
`cacheTag` still pairs with the webhook below; `cacheLife("minutes")` replaces
|
|
225
|
+
the client's `revalidate`, which the cached scope no longer consults.
|
|
226
|
+
|
|
145
227
|
## Dropping the cache when PokoBlog publishes
|
|
146
228
|
|
|
147
229
|
```ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pokoblog/next",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Server components and metadata helpers for rendering a PokoBlog blog in Next.js.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -45,5 +45,13 @@
|
|
|
45
45
|
"react-dom": "19.2.8",
|
|
46
46
|
"typescript": "7.0.2",
|
|
47
47
|
"vitest": "4.1.10"
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "git+https://github.com/HeyPoko/pokoblog-next.git"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/HeyPoko/pokoblog-next#readme",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/HeyPoko/pokoblog-next/issues"
|
|
48
56
|
}
|
|
49
57
|
}
|