Skip to content

Commit d789452

Browse files
fix(content): clear route cache on content changes so slug pages reflect updated data (#15573)
* fix(content): clear route cache on content changes so slug pages reflect updated data * Add changeset * test: cover HMR updates for content slug routes --------- Co-authored-by: astrobot-houston <[email protected]>
1 parent 170ed89 commit d789452

7 files changed

Lines changed: 64 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"astro": patch
3+
---
4+
5+
Clear the route cache on content changes so slug pages reflect updated data during dev.

packages/astro/src/content/vite-plugin-content-virtual-mod.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ function invalidateDataStore(viteServer: ViteDevServer) {
3939
// Pass `true` to mark this as HMR invalidation so Vite drops cached SSR results.
4040
environment.moduleGraph.invalidateModule(module, undefined, timestamp, true);
4141
}
42+
// Signal the SSR runner to clear its route cache so that getStaticPaths()
43+
// is re-evaluated with the updated content collection data.
44+
environment.hot.send('astro:content-changed', {});
4245
viteServer.environments.client.hot.send({
4346
type: 'full-reload',
4447
path: '*',

packages/astro/src/core/app/entrypoints/virtual/dev.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ export const createApp: CreateApp = ({ streaming } = {}) => {
2626
logger.error('router', `Failed to update routes via HMR:\n ${e}`);
2727
}
2828
});
29+
30+
// Listen for content collection changes via HMR.
31+
// Clear the route cache so getStaticPaths() is re-evaluated with fresh data.
32+
import.meta.hot.on('astro:content-changed', () => {
33+
if (!currentDevApp) return;
34+
currentDevApp.pipeline.routeCache.clearAll();
35+
});
2936
}
3037

3138
return currentDevApp;

packages/astro/src/vite-plugin-app/app.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ export class AstroServerApp extends BaseApp<RunnablePipeline> {
6161
ensure404Route(this.manifestData);
6262
}
6363

64+
/**
65+
* Clears the route cache so that getStaticPaths() is re-evaluated.
66+
* Called via HMR when content collection data changes.
67+
*/
68+
clearRouteCache(): void {
69+
this.pipeline.clearRouteCache();
70+
}
71+
6472
async devMatch(pathname: string): Promise<DevMatch | undefined> {
6573
const matchedRoute = await matchRoute(
6674
pathname,

packages/astro/src/vite-plugin-app/createAstroServerApp.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ export default async function createAstroServerApp(
7171
actualLogger.error('router', `Failed to update routes via HMR:\n ${e}`);
7272
}
7373
});
74+
75+
// Listen for content collection changes via HMR.
76+
// Clear the route cache so getStaticPaths() is re-evaluated with fresh data.
77+
import.meta.hot.on('astro:content-changed', () => {
78+
app.clearRouteCache();
79+
actualLogger.debug('router', 'Route cache cleared due to content change');
80+
});
7481
}
7582

7683
return {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
import { getCollection, render } from 'astro:content';
3+
4+
export async function getStaticPaths() {
5+
const posts = await getCollection('blog');
6+
return posts.map((post) => ({ params: { slug: post.id }, props: { post } }));
7+
}
8+
9+
const { post } = Astro.props;
10+
11+
const { Content } = await render(post);
12+
---
13+
14+
<html>
15+
<head>
16+
<title>{post.data.title}</title>
17+
</head>
18+
<body>
19+
<h1>{post.data.title}</h1>
20+
<div id="post-body">
21+
<Content />
22+
</div>
23+
</body>
24+
</html>

packages/astro/test/hmr-markdown.test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,23 @@ describe('HMR: Markdown updates', () => {
3232
let html = await response.text();
3333
assert.ok(html.includes('Original content'));
3434

35+
response = await fixture.fetch('/blog/post');
36+
assert.equal(response.status, 200);
37+
html = await response.text();
38+
assert.ok(html.includes('Original content'));
39+
3540
await fixture.editFile(markdownPath, UPDATED_CONTENT);
3641
await fixture.onNextDataStoreChange();
3742

3843
response = await fixture.fetch('/');
3944
assert.equal(response.status, 200);
4045
html = await response.text();
4146
assert.ok(html.includes('Updated content'));
47+
48+
response = await fixture.fetch('/blog/post');
49+
assert.equal(response.status, 200);
50+
html = await response.text();
51+
assert.ok(html.includes('Updated content'));
4252
},
4353
);
4454
});

0 commit comments

Comments
 (0)