Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/clear-route-cache-content.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"astro": patch
---

Clear the route cache on content changes so slug pages reflect updated data during dev.
3 changes: 3 additions & 0 deletions packages/astro/src/content/vite-plugin-content-virtual-mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ function invalidateDataStore(viteServer: ViteDevServer) {
// Pass `true` to mark this as HMR invalidation so Vite drops cached SSR results.
environment.moduleGraph.invalidateModule(module, undefined, timestamp, true);
}
// Signal the SSR runner to clear its route cache so that getStaticPaths()
// is re-evaluated with the updated content collection data.
environment.hot.send('astro:content-changed', {});
viteServer.environments.client.hot.send({
type: 'full-reload',
path: '*',
Expand Down
7 changes: 7 additions & 0 deletions packages/astro/src/core/app/entrypoints/virtual/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ export const createApp: CreateApp = ({ streaming } = {}) => {
logger.error('router', `Failed to update routes via HMR:\n ${e}`);
}
});

// Listen for content collection changes via HMR.
// Clear the route cache so getStaticPaths() is re-evaluated with fresh data.
import.meta.hot.on('astro:content-changed', () => {
if (!currentDevApp) return;
currentDevApp.pipeline.routeCache.clearAll();
});
}

return currentDevApp;
Expand Down
8 changes: 8 additions & 0 deletions packages/astro/src/vite-plugin-app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ export class AstroServerApp extends BaseApp<RunnablePipeline> {
ensure404Route(this.manifestData);
}

/**
* Clears the route cache so that getStaticPaths() is re-evaluated.
* Called via HMR when content collection data changes.
*/
clearRouteCache(): void {
this.pipeline.clearRouteCache();
}

async devMatch(pathname: string): Promise<DevMatch | undefined> {
const matchedRoute = await matchRoute(
pathname,
Expand Down
7 changes: 7 additions & 0 deletions packages/astro/src/vite-plugin-app/createAstroServerApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ export default async function createAstroServerApp(
actualLogger.error('router', `Failed to update routes via HMR:\n ${e}`);
}
});

// Listen for content collection changes via HMR.
// Clear the route cache so getStaticPaths() is re-evaluated with fresh data.
import.meta.hot.on('astro:content-changed', () => {
app.clearRouteCache();
actualLogger.debug('router', 'Route cache cleared due to content change');
});
}

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
import { getCollection, render } from 'astro:content';

export async function getStaticPaths() {
const posts = await getCollection('blog');
return posts.map((post) => ({ params: { slug: post.id }, props: { post } }));
}

const { post } = Astro.props;

const { Content } = await render(post);
---

<html>
<head>
<title>{post.data.title}</title>
</head>
<body>
<h1>{post.data.title}</h1>
<div id="post-body">
<Content />
</div>
</body>
</html>
10 changes: 10 additions & 0 deletions packages/astro/test/hmr-markdown.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,23 @@ describe('HMR: Markdown updates', () => {
let html = await response.text();
assert.ok(html.includes('Original content'));

response = await fixture.fetch('/blog/post');
assert.equal(response.status, 200);
html = await response.text();
assert.ok(html.includes('Original content'));

await fixture.editFile(markdownPath, UPDATED_CONTENT);
await fixture.onNextDataStoreChange();

response = await fixture.fetch('/');
assert.equal(response.status, 200);
html = await response.text();
assert.ok(html.includes('Updated content'));

response = await fixture.fetch('/blog/post');
assert.equal(response.status, 200);
html = await response.text();
assert.ok(html.includes('Updated content'));
},
);
});
Loading