summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Matthew Lee <mdlee.md+github@gmail.com> 2024-08-07 09:55:27 -0500
committerGravatar GitHub <noreply@github.com> 2024-08-07 15:55:27 +0100
commit9aaf58c1339b54f2c1394e718a0f6f609f0b6342 (patch)
tree9ac04e57013ca52b09fca0717274495d5051270f
parentca45fd93c14f9f03cdecabd47a7e4b67ff001a12 (diff)
downloadastro-9aaf58c1339b54f2c1394e718a0f6f609f0b6342.tar.gz
astro-9aaf58c1339b54f2c1394e718a0f6f609f0b6342.tar.zst
astro-9aaf58c1339b54f2c1394e718a0f6f609f0b6342.zip
Consistent file hashes (#11628)
* Fix css plugin having inconsistent builds in different environments Astro's css plugin generates chunk ids that include a hash of all of the chunk's parent ids. These ids are currently the absolute file paths of the parent files. The generated chunk ids are then inserted into those pages as import statements. Because these import statements include a hash based on these absolute file paths, this causes rollup to generate different hashes for those pages when a build is run in different environments. The exact same project will produce identical assets with different filenames when built on different machines, or when built from different directories on the same machine, etc. To fix this, I've stripped out the working directory of these file paths before they are added to the hash. This means that the hash will still change if the files referencing it chacnge (which I believe is the intended behavior), but will be stable if the entire project is built in different environments. * add changeset * fixup! use settings.config.root and vite's normalizePath I've chosen to update the function signature of shortHashedName to match createSlugger's, so it now accepts the settings object and returns the actual hashing function. This way, createSlugger's function signature doesn't need to update to needlessly accept an additional argument. * fixup! remove unused import * Update .changeset/young-pillows-shave.md Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com> * fixup! use fileURLtoPath --------- Co-authored-by: Matt Lee <mdlee.md@gmail.com> Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com>
-rw-r--r--.changeset/young-pillows-shave.md5
-rw-r--r--packages/astro/src/core/build/css-asset-name.ts31
-rw-r--r--packages/astro/src/core/build/plugins/plugin-css.ts4
3 files changed, 30 insertions, 10 deletions
diff --git a/.changeset/young-pillows-shave.md b/.changeset/young-pillows-shave.md
new file mode 100644
index 000000000..e3d8c4d5d
--- /dev/null
+++ b/.changeset/young-pillows-shave.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Ensures consistent CSS chunk hashes across different environments
diff --git a/packages/astro/src/core/build/css-asset-name.ts b/packages/astro/src/core/build/css-asset-name.ts
index 4172a1cbb..1876c0877 100644
--- a/packages/astro/src/core/build/css-asset-name.ts
+++ b/packages/astro/src/core/build/css-asset-name.ts
@@ -2,6 +2,8 @@ import type { GetModuleInfo, ModuleInfo } from 'rollup';
import crypto from 'node:crypto';
import npath from 'node:path';
+import { fileURLToPath } from 'node:url';
+import { normalizePath } from 'vite';
import type { AstroSettings } from '../../@types/astro.js';
import { viteID } from '../util.js';
import { getTopLevelPageModuleInfos } from './graph.js';
@@ -13,19 +15,32 @@ const confusingBaseNames = ['404', '500'];
// The short name for when the hash can be included
// We could get rid of this and only use the createSlugger implementation, but this creates
// slightly prettier names.
-export function shortHashedName(id: string, ctx: { getModuleInfo: GetModuleInfo }): string {
- const parents = getTopLevelPageModuleInfos(id, ctx);
- return createNameHash(
- getFirstParentId(parents),
- parents.map((page) => page.id)
- );
+export function shortHashedName(settings: AstroSettings) {
+ return function (id: string, ctx: { getModuleInfo: GetModuleInfo }): string {
+ const parents = getTopLevelPageModuleInfos(id, ctx);
+ return createNameHash(
+ getFirstParentId(parents),
+ parents.map((page) => page.id),
+ settings
+ );
+ };
}
-export function createNameHash(baseId: string | undefined, hashIds: string[]): string {
+export function createNameHash(
+ baseId: string | undefined,
+ hashIds: string[],
+ settings: AstroSettings
+): string {
const baseName = baseId ? prettifyBaseName(npath.parse(baseId).name) : 'index';
const hash = crypto.createHash('sha256');
+ const root = fileURLToPath(settings.config.root);
+
for (const id of hashIds) {
- hash.update(id, 'utf-8');
+ // Strip the project directory from the paths before they are hashed, so that assets
+ // that import these css files have consistent hashes when built in different environments.
+ const relativePath = npath.relative(root, id);
+ // Normalize the path to fix differences between windows and other environments
+ hash.update(normalizePath(relativePath), 'utf-8');
}
const h = hash.digest('hex').slice(0, 8);
const proposedName = baseName + '.' + h;
diff --git a/packages/astro/src/core/build/plugins/plugin-css.ts b/packages/astro/src/core/build/plugins/plugin-css.ts
index 9ac29ebe0..269364842 100644
--- a/packages/astro/src/core/build/plugins/plugin-css.ts
+++ b/packages/astro/src/core/build/plugins/plugin-css.ts
@@ -70,7 +70,7 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
const assetFileNames = outputOptions.assetFileNames;
const namingIncludesHash = assetFileNames?.toString().includes('[hash]');
const createNameForParentPages = namingIncludesHash
- ? assetName.shortHashedName
+ ? assetName.shortHashedName(settings)
: assetName.createSlugger(settings);
extendManualChunks(outputOptions, {
@@ -94,7 +94,7 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
if (hasAssetPropagationFlag(pageInfo.id)) {
// Split delayed assets to separate modules
// so they can be injected where needed
- const chunkId = assetName.createNameHash(id, [id]);
+ const chunkId = assetName.createNameHash(id, [id], settings);
internals.cssModuleToChunkIdMap.set(id, chunkId);
return chunkId;
}