summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Matt Kane <m@mk.gg> 2024-12-18 14:01:56 +0000
committerGravatar GitHub <noreply@github.com> 2024-12-18 14:01:56 +0000
commit36c1e0697da9fdc453a7a9a3c84e0e79cd0cb376 (patch)
treed84c9b2976d05ed65ada4cc56d4db24fd05d9a04
parenta581c152fce75e5dc0d991e4259c96de090db208 (diff)
downloadastro-36c1e0697da9fdc453a7a9a3c84e0e79cd0cb376.tar.gz
astro-36c1e0697da9fdc453a7a9a3c84e0e79cd0cb376.tar.zst
astro-36c1e0697da9fdc453a7a9a3c84e0e79cd0cb376.zip
fix: clear the content layer cache when the Astro config changes (#12767)
* fix: clear the content layer cache when the Astro config changes * Use deterministic-object-hash * Switch back to safe-stringify * Whitespace
-rw-r--r--.changeset/shaggy-dancers-run.md5
-rw-r--r--packages/astro/src/content/content-layer.ts26
-rw-r--r--packages/astro/src/content/utils.ts23
-rw-r--r--packages/astro/test/content-layer.test.js14
-rw-r--r--packages/astro/test/fixtures/content-layer/astro.config.mjs3
5 files changed, 66 insertions, 5 deletions
diff --git a/.changeset/shaggy-dancers-run.md b/.changeset/shaggy-dancers-run.md
new file mode 100644
index 000000000..e95c16dd7
--- /dev/null
+++ b/.changeset/shaggy-dancers-run.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Clears the content layer cache when the Astro config is changed
diff --git a/packages/astro/src/content/content-layer.ts b/packages/astro/src/content/content-layer.ts
index e8c772a2c..c03952953 100644
--- a/packages/astro/src/content/content-layer.ts
+++ b/packages/astro/src/content/content-layer.ts
@@ -19,6 +19,7 @@ import {
getEntryConfigByExtMap,
getEntryDataAndImages,
globalContentConfigObserver,
+ safeStringify,
} from './utils.js';
export interface ContentLayerOptions {
@@ -87,7 +88,7 @@ export class ContentLayer {
// It uses wasm, so we need to load it asynchronously.
const { h64ToString } = await xxhash();
- this.#generateDigest = (data: Record<string, unknown> | string) => {
+ this.#generateDigest = (data: unknown) => {
const dataString = typeof data === 'string' ? data : JSON.stringify(data);
return h64ToString(dataString);
};
@@ -143,12 +144,28 @@ export class ContentLayer {
}
logger.info('Syncing content');
+ const {
+ vite: _vite,
+ integrations: _integrations,
+ adapter: _adapter,
+ ...hashableConfig
+ } = this.#settings.config;
+
+ const astroConfigDigest = safeStringify(hashableConfig);
+
const { digest: currentConfigDigest } = contentConfig.config;
this.#lastConfigDigest = currentConfigDigest;
let shouldClear = false;
- const previousConfigDigest = await this.#store.metaStore().get('config-digest');
+ const previousConfigDigest = await this.#store.metaStore().get('content-config-digest');
+ const previousAstroConfigDigest = await this.#store.metaStore().get('astro-config-digest');
const previousAstroVersion = await this.#store.metaStore().get('astro-version');
+
+ if (previousAstroConfigDigest && previousAstroConfigDigest !== astroConfigDigest) {
+ logger.info('Astro config changed');
+ shouldClear = true;
+ }
+
if (currentConfigDigest && previousConfigDigest !== currentConfigDigest) {
logger.info('Content config changed');
shouldClear = true;
@@ -165,7 +182,10 @@ export class ContentLayer {
await this.#store.metaStore().set('astro-version', process.env.ASTRO_VERSION);
}
if (currentConfigDigest) {
- await this.#store.metaStore().set('config-digest', currentConfigDigest);
+ await this.#store.metaStore().set('content-config-digest', currentConfigDigest);
+ }
+ if (astroConfigDigest) {
+ await this.#store.metaStore().set('astro-config-digest', astroConfigDigest);
}
await Promise.all(
Object.entries(contentConfig.config.collections).map(async ([name, collection]) => {
diff --git a/packages/astro/src/content/utils.ts b/packages/astro/src/content/utils.ts
index 3b9588c0b..32d53f5db 100644
--- a/packages/astro/src/content/utils.ts
+++ b/packages/astro/src/content/utils.ts
@@ -832,3 +832,26 @@ export function contentModuleToId(fileName: string) {
params.set(CONTENT_MODULE_FLAG, 'true');
return `${DEFERRED_MODULE}?${params.toString()}`;
}
+
+// Based on https://github.com/sindresorhus/safe-stringify
+function safeStringifyReplacer(seen: WeakSet<object>) {
+ return function (_key: string, value: unknown) {
+ if (!(value !== null && typeof value === 'object')) {
+ return value;
+ }
+ if (seen.has(value)) {
+ return '[Circular]';
+ }
+ seen.add(value);
+ const newValue = Array.isArray(value) ? [] : {};
+ for (const [key2, value2] of Object.entries(value)) {
+ (newValue as Record<string, unknown>)[key2] = safeStringifyReplacer(seen)(key2, value2);
+ }
+ seen.delete(value);
+ return newValue;
+ };
+}
+export function safeStringify(value: unknown) {
+ const seen = new WeakSet();
+ return JSON.stringify(value, safeStringifyReplacer(seen));
+}
diff --git a/packages/astro/test/content-layer.test.js b/packages/astro/test/content-layer.test.js
index 41d2f0fce..0a7e2b289 100644
--- a/packages/astro/test/content-layer.test.js
+++ b/packages/astro/test/content-layer.test.js
@@ -288,7 +288,7 @@ describe('Content Layer', () => {
assert.equal(newJson.entryWithReference.data.something?.content, 'transform me');
});
- it('clears the store on new build if the config has changed', async () => {
+ it('clears the store on new build if the content config has changed', async () => {
let newJson = devalue.parse(await fixture.readFile('/collections.json'));
assert.equal(newJson.increment.data.lastValue, 1);
await fixture.editFile('src/content.config.ts', (prev) => {
@@ -299,6 +299,18 @@ describe('Content Layer', () => {
assert.equal(newJson.increment.data.lastValue, 1);
await fixture.resetAllFiles();
});
+
+ it('clears the store on new build if the Astro config has changed', async () => {
+ let newJson = devalue.parse(await fixture.readFile('/collections.json'));
+ assert.equal(newJson.increment.data.lastValue, 1);
+ await fixture.editFile('astro.config.mjs', (prev) => {
+ return prev.replace('Astro content layer', 'Astro more content layer');
+ });
+ await fixture.build();
+ newJson = devalue.parse(await fixture.readFile('/collections.json'));
+ assert.equal(newJson.increment.data.lastValue, 1);
+ await fixture.resetAllFiles();
+ });
});
describe('Dev', () => {
diff --git a/packages/astro/test/fixtures/content-layer/astro.config.mjs b/packages/astro/test/fixtures/content-layer/astro.config.mjs
index 6b56f41fd..06f4f45d9 100644
--- a/packages/astro/test/fixtures/content-layer/astro.config.mjs
+++ b/packages/astro/test/fixtures/content-layer/astro.config.mjs
@@ -3,7 +3,8 @@ import { defineConfig } from 'astro/config';
import { fileURLToPath } from 'node:url';
export default defineConfig({
- integrations: [mdx(), {
+ name: 'Astro content layer',
+ integrations: [mdx(), {
name: '@astrojs/my-integration',
hooks: {
'astro:server:setup': async ({ server, refreshContent }) => {