mirror of
https://github.com/withastro/astro.git
synced 2024-12-30 22:03:56 -05:00
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
This commit is contained in:
parent
a581c152fc
commit
36c1e0697d
5 changed files with 66 additions and 5 deletions
5
.changeset/shaggy-dancers-run.md
Normal file
5
.changeset/shaggy-dancers-run.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Clears the content layer cache when the Astro config is changed
|
|
@ -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]) => {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -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 }) => {
|
||||
|
|
Loading…
Reference in a new issue