diff --git a/packages/astro/src/core/build/plugins/plugin-content.ts b/packages/astro/src/core/build/plugins/plugin-content.ts index ce11359d8325..24512f8ebc8e 100644 --- a/packages/astro/src/core/build/plugins/plugin-content.ts +++ b/packages/astro/src/core/build/plugins/plugin-content.ts @@ -3,7 +3,6 @@ import fsMod from 'node:fs'; import { fileURLToPath } from 'node:url'; import pLimit from 'p-limit'; import { type Plugin as VitePlugin, normalizePath } from 'vite'; -import { configPaths } from '../../config/index.js'; import { CONTENT_RENDER_FLAG, PROPAGATED_ASSET_FLAG } from '../../../content/consts.js'; import { type ContentLookupMap, hasContentFlag } from '../../../content/utils.js'; import { @@ -11,16 +10,22 @@ import { generateLookupMap, } from '../../../content/vite-plugin-content-virtual-mod.js'; import { isServerLikeOutput } from '../../../prerender/utils.js'; -import { joinPaths, removeFileExtension, removeLeadingForwardSlash, appendForwardSlash } from '../../path.js'; +import { configPaths } from '../../config/index.js'; +import { emptyDir } from '../../fs/index.js'; +import { + appendForwardSlash, + joinPaths, + removeFileExtension, + removeLeadingForwardSlash, +} from '../../path.js'; import { addRollupInput } from '../add-rollup-input.js'; +import { CHUNKS_PATH } from '../consts.js'; import { type BuildInternals } from '../internal.js'; import type { AstroBuildPlugin } from '../plugin.js'; import { copyFiles } from '../static-build.js'; import type { StaticBuildOptions } from '../types.js'; import { encodeName } from '../util.js'; import { extendManualChunks } from './util.js'; -import { emptyDir } from '../../fs/index.js'; -import { CHUNKS_PATH } from '../consts.js'; const CONTENT_CACHE_DIR = './content/'; const CONTENT_MANIFEST_FILE = './manifest.json'; @@ -54,14 +59,21 @@ const resolvedVirtualEmptyModuleId = `\0${virtualEmptyModuleId}`; const NO_MANIFEST_VERSION = -1 as const; function createContentManifest(): ContentManifest { - return { version: NO_MANIFEST_VERSION, entries: [], serverEntries: [], clientEntries: [], lockfiles: "", configs: "" }; + return { + version: NO_MANIFEST_VERSION, + entries: [], + serverEntries: [], + clientEntries: [], + lockfiles: '', + configs: '', + }; } function vitePluginContent( opts: StaticBuildOptions, lookupMap: ContentLookupMap, internals: BuildInternals, - cachedBuildOutput: Array<{ cached: URL; dist: URL; }> + cachedBuildOutput: Array<{ cached: URL; dist: URL }> ): VitePlugin { const { config } = opts.settings; const { cacheDir } = config; @@ -93,11 +105,11 @@ function vitePluginContent( // If the manifest is valid, use the cached client entries as nothing has changed currentManifestState = manifestState(oldManifest, newManifest); - if(currentManifestState === 'valid') { + if (currentManifestState === 'valid') { internals.cachedClientEntries = oldManifest.clientEntries; } else { let logReason = ''; - switch(currentManifestState) { + switch (currentManifestState) { case 'config-mismatch': logReason = 'Astro config has changed'; break; @@ -133,8 +145,8 @@ function vitePluginContent( // Restores cached chunks and assets from the previous build // If the manifest state is not valid then it needs to rebuild everything // so don't do that in this case. - if(currentManifestState === 'valid') { - for(const { cached, dist } of cachedBuildOutput) { + if (currentManifestState === 'valid') { + for (const { cached, dist } of cachedBuildOutput) { if (fsMod.existsSync(cached)) { await copyFiles(cached, dist, true); } @@ -243,7 +255,7 @@ function vitePluginContent( const cacheExists = fsMod.existsSync(contentCacheDir); // If the manifest is invalid, empty the cache so that we can create a new one. - if(cacheExists && currentManifestState !== 'valid') { + if (cacheExists && currentManifestState !== 'valid') { emptyDir(contentCacheDir); } @@ -310,26 +322,32 @@ function getEntriesFromManifests( return entries; } -type ManifestState = 'valid' | 'no-manifest' | 'version-mismatch' | 'no-entries' | 'lockfile-mismatch' | 'config-mismatch'; +type ManifestState = + | 'valid' + | 'no-manifest' + | 'version-mismatch' + | 'no-entries' + | 'lockfile-mismatch' + | 'config-mismatch'; function manifestState(oldManifest: ContentManifest, newManifest: ContentManifest): ManifestState { // There isn't an existing manifest. - if(oldManifest.version === NO_MANIFEST_VERSION) { + if (oldManifest.version === NO_MANIFEST_VERSION) { return 'no-manifest'; } // Version mismatch, always invalid if (oldManifest.version !== newManifest.version) { return 'version-mismatch'; } - if(oldManifest.entries.length === 0) { + if (oldManifest.entries.length === 0) { return 'no-entries'; } // Lockfiles have changed or there is no lockfile at all. - if((oldManifest.lockfiles !== newManifest.lockfiles) || newManifest.lockfiles === '') { + if (oldManifest.lockfiles !== newManifest.lockfiles || newManifest.lockfiles === '') { return 'lockfile-mismatch'; } // Config has changed. - if(oldManifest.configs !== newManifest.configs) { + if (oldManifest.configs !== newManifest.configs) { return 'config-mismatch'; } return 'valid'; @@ -356,10 +374,10 @@ async function generateContentManifest( ); } } - + const [lockfiles, configs] = await Promise.all([ lockfilesHash(opts.settings.config.root), - configHash(opts.settings.config.root) + configHash(opts.settings.config.root), ]); manifest.lockfiles = lockfiles; @@ -385,7 +403,7 @@ async function lockfilesHash(root: URL) { const lockfiles = ['package-lock.json', 'pnpm-lock.yaml', 'yarn.lock', 'bun.lockb']; const datas: Uint8Array[] = []; const promises: Promise[] = []; - for(const lockfileName of lockfiles) { + for (const lockfileName of lockfiles) { const fileURL = new URL(`./${lockfileName}`, root); promises.push(pushBufferInto(fileURL, datas)); } @@ -395,7 +413,7 @@ async function lockfilesHash(root: URL) { async function configHash(root: URL) { const configFileNames = configPaths; - for(const configPath of configFileNames) { + for (const configPath of configFileNames) { try { const fileURL = new URL(`./${configPath}`, root); const data = await fsMod.promises.readFile(fileURL); @@ -411,7 +429,7 @@ async function configHash(root: URL) { function checksum(...datas: string[] | Uint8Array[]): string { const hash = createHash('sha1'); - datas.forEach(data => hash.update(data)); + datas.forEach((data) => hash.update(data)); return hash.digest('base64'); } @@ -458,7 +476,7 @@ export function pluginContent( return; } // Cache build output of chunks and assets - for(const { cached, dist } of cachedBuildOutput) { + for (const { cached, dist } of cachedBuildOutput) { if (fsMod.existsSync(dist)) { await copyFiles(dist, cached, true); } diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index ede0e36e35a4..cdd24e1c0053 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -23,6 +23,7 @@ import { PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js'; import { AstroError, AstroErrorData } from '../errors/index.js'; import { routeIsRedirect } from '../redirects/index.js'; import { getOutDirWithinCwd } from './common.js'; +import { CHUNKS_PATH } from './consts.js'; import { generatePages } from './generate.js'; import { trackPageData } from './internal.js'; import { type AstroBuildPluginContainer, createPluginContainer } from './plugin.js'; @@ -34,7 +35,6 @@ import { RESOLVED_SPLIT_MODULE_ID, RESOLVED_SSR_VIRTUAL_MODULE_ID } from './plug import { ASTRO_PAGE_EXTENSION_POST_PATTERN } from './plugins/util.js'; import type { StaticBuildOptions } from './types.js'; import { encodeName, getTimeStat, viteBuildReturnToRollupOutputs } from './util.js'; -import { CHUNKS_PATH } from './consts.js'; export async function viteBuild(opts: StaticBuildOptions) { const { allPages, settings } = opts; diff --git a/packages/astro/src/core/config/index.ts b/packages/astro/src/core/config/index.ts index 0f697ddd608d..3beaa5663523 100644 --- a/packages/astro/src/core/config/index.ts +++ b/packages/astro/src/core/config/index.ts @@ -1,4 +1,10 @@ -export { configPaths, resolveConfig, resolveConfigPath, resolveFlags, resolveRoot } from './config.js'; +export { + configPaths, + resolveConfig, + resolveConfigPath, + resolveFlags, + resolveRoot, +} from './config.js'; export { createNodeLogger } from './logging.js'; export { mergeConfig } from './merge.js'; export type { AstroConfigType } from './schema.js'; diff --git a/packages/astro/src/integrations/index.ts b/packages/astro/src/integrations/index.ts index 7603f24a6065..81901737e931 100644 --- a/packages/astro/src/integrations/index.ts +++ b/packages/astro/src/integrations/index.ts @@ -480,7 +480,13 @@ type RunHookBuildDone = { cacheManifest: boolean; }; -export async function runHookBuildDone({ config, pages, routes, logging, cacheManifest }: RunHookBuildDone) { +export async function runHookBuildDone({ + config, + pages, + routes, + logging, + cacheManifest, +}: RunHookBuildDone) { const dir = isServerLikeOutput(config) ? config.build.client : config.outDir; await fs.promises.mkdir(dir, { recursive: true }); diff --git a/packages/astro/src/vite-plugin-astro/index.ts b/packages/astro/src/vite-plugin-astro/index.ts index c33f5dd0c768..9d6367b99d0f 100644 --- a/packages/astro/src/vite-plugin-astro/index.ts +++ b/packages/astro/src/vite-plugin-astro/index.ts @@ -92,13 +92,13 @@ export default function astro({ settings, logger }: AstroPluginOptions): vite.Pl if (!compileMetadata) { // If `compileMetadata` doesn't exist in dev, that means the virtual module may have been invalidated. // We try to re-compile the main Astro module (`filename`) first before retrieving the metadata again. - if(server) { + if (server) { const code = await loadId(server.pluginContainer, filename); // `compile` should re-set `filename` in `astroFileToCompileMetadata` if (code != null) await compile(code, filename); } // When cached we might load client-side scripts during the build - else if(config.experimental.contentCollectionCache) { + else if (config.experimental.contentCollectionCache) { await this.load({ id: filename, resolveDependencies: false, diff --git a/packages/astro/test/experimental-content-collections-cache-invalidation.test.js b/packages/astro/test/experimental-content-collections-cache-invalidation.test.js index 5ec688a91ba1..abc8ea839370 100644 --- a/packages/astro/test/experimental-content-collections-cache-invalidation.test.js +++ b/packages/astro/test/experimental-content-collections-cache-invalidation.test.js @@ -1,8 +1,8 @@ import assert from 'node:assert/strict'; -import { after, before, describe, it } from 'node:test'; -import { loadFixture } from './test-utils.js'; import fs from 'node:fs'; +import { after, before, describe, it } from 'node:test'; import { copyFiles } from '../dist/core/build/static-build.js'; +import { loadFixture } from './test-utils.js'; describe('Experimental Content Collections cache - invalidation', () => { class CacheBackup { @@ -32,27 +32,29 @@ describe('Experimental Content Collections cache - invalidation', () => { hooks: { 'astro:build:done': ({ cacheManifest }) => { this.used = cacheManifest; - } - } - } + }, + }, + }; } } describe('manifest version', () => { - let fixture, backup, - /** @type {ManifestTestPlugin} */ - testPlugin; + let fixture, + backup, + /** @type {ManifestTestPlugin} */ + testPlugin; before(async () => { testPlugin = new ManifestTestPlugin(); fixture = await loadFixture({ root: './fixtures/content-collections-cache-invalidation/', cacheDir: './cache/version-mismatch/', experimental: { contentCollectionCache: true }, - integrations: [ - testPlugin.plugin() - ] + integrations: [testPlugin.plugin()], }); - backup = new CacheBackup('./fixtures/content-collections-cache-invalidation/', './cache/version-mismatch/'); + backup = new CacheBackup( + './fixtures/content-collections-cache-invalidation/', + './cache/version-mismatch/' + ); backup.backup(); await fixture.build(); }); @@ -68,20 +70,22 @@ describe('Experimental Content Collections cache - invalidation', () => { }); describe('lockfiles', () => { - let fixture, backup, - /** @type {ManifestTestPlugin} */ - testPlugin; + let fixture, + backup, + /** @type {ManifestTestPlugin} */ + testPlugin; before(async () => { testPlugin = new ManifestTestPlugin(); fixture = await loadFixture({ root: './fixtures/content-collections-cache-invalidation/', cacheDir: './cache/lockfile-mismatch/', experimental: { contentCollectionCache: true }, - integrations: [ - testPlugin.plugin() - ] + integrations: [testPlugin.plugin()], }); - backup = new CacheBackup('./fixtures/content-collections-cache-invalidation/', './cache/lockfile-mismatch/'); + backup = new CacheBackup( + './fixtures/content-collections-cache-invalidation/', + './cache/lockfile-mismatch/' + ); backup.backup(); await fixture.build(); });