Make CSS chunk names less confusing (#8754)

This commit is contained in:
Bjorn Lu 2023-10-09 17:29:28 +08:00 committed by GitHub
parent eaed844ea8
commit 93b092266f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 22 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Make CSS chunk names less confusing

View file

@ -1,4 +1,4 @@
import type { GetModuleInfo } from 'rollup'; import type { GetModuleInfo, ModuleInfo } from 'rollup';
import crypto from 'node:crypto'; import crypto from 'node:crypto';
import npath from 'node:path'; import npath from 'node:path';
@ -6,20 +6,29 @@ import type { AstroSettings } from '../../@types/astro.js';
import { viteID } from '../util.js'; import { viteID } from '../util.js';
import { getTopLevelPages } from './graph.js'; import { getTopLevelPages } from './graph.js';
// These pages could be used as base names for the chunk hashed name, but they are confusing
// and should be avoided it possible
const confusingBaseNames = ['404', '500'];
// The short name for when the hash can be included // 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 // We could get rid of this and only use the createSlugger implementation, but this creates
// slightly prettier names. // slightly prettier names.
export function shortHashedName(id: string, ctx: { getModuleInfo: GetModuleInfo }): string { export function shortHashedName(id: string, ctx: { getModuleInfo: GetModuleInfo }): string {
const parents = Array.from(getTopLevelPages(id, ctx)); const parents = Array.from(getTopLevelPages(id, ctx));
const firstParentId = parents[0]?.[0].id; return createNameHash(
const firstParentName = firstParentId ? npath.parse(firstParentId).name : 'index'; getFirstParentId(parents),
parents.map(([page]) => page.id)
);
}
export function createNameHash(baseId: string | undefined, hashIds: string[]): string {
const baseName = baseId ? prettifyBaseName(npath.parse(baseId).name) : 'index';
const hash = crypto.createHash('sha256'); const hash = crypto.createHash('sha256');
for (const [page] of parents) { for (const id of hashIds) {
hash.update(page.id, 'utf-8'); hash.update(id, 'utf-8');
} }
const h = hash.digest('hex').slice(0, 8); const h = hash.digest('hex').slice(0, 8);
const proposedName = firstParentName + '.' + h; const proposedName = baseName + '.' + h;
return proposedName; return proposedName;
} }
@ -34,7 +43,7 @@ export function createSlugger(settings: AstroSettings) {
.map(([page]) => page.id) .map(([page]) => page.id)
.sort() .sort()
.join('-'); .join('-');
const firstParentId = parents[0]?.[0].id || indexPage; const firstParentId = getFirstParentId(parents) || indexPage;
// Use the last two segments, for ex /docs/index // Use the last two segments, for ex /docs/index
let dir = firstParentId; let dir = firstParentId;
@ -45,7 +54,7 @@ export function createSlugger(settings: AstroSettings) {
break; break;
} }
const name = npath.parse(npath.basename(dir)).name; const name = prettifyBaseName(npath.parse(npath.basename(dir)).name);
key = key.length ? name + sep + key : name; key = key.length ? name + sep + key : name;
dir = npath.dirname(dir); dir = npath.dirname(dir);
i++; i++;
@ -76,3 +85,32 @@ export function createSlugger(settings: AstroSettings) {
return name; return name;
}; };
} }
/**
* Find the first parent id from `parents` where its name is not confusing.
* Returns undefined if there's no parents.
*/
function getFirstParentId(parents: [ModuleInfo, number, number][]) {
for (const parent of parents) {
const id = parent[0].id;
const baseName = npath.parse(id).name;
if (!confusingBaseNames.includes(baseName)) {
return id;
}
}
// If all parents are confusing, just use the first one. Or if there's no
// parents, this will return undefined.
return parents[0]?.[0].id;
}
const charsToReplaceRe = /[.\[\]]/g;
const underscoresRe = /_+/g;
/**
* Prettify base names so they're easier to read:
* - index -> index
* - [slug] -> _slug_
* - [...spread] -> _spread_
*/
function prettifyBaseName(str: string) {
return str.replace(charsToReplaceRe, '_').replace(underscoresRe, '_');
}

View file

@ -1,5 +1,3 @@
import * as crypto from 'node:crypto';
import * as npath from 'node:path';
import type { GetModuleInfo } from 'rollup'; import type { GetModuleInfo } from 'rollup';
import { type ResolvedConfig, type Plugin as VitePlugin } from 'vite'; import { type ResolvedConfig, type Plugin as VitePlugin } from 'vite';
import { isBuildableCSSRequest } from '../../../vite-plugin-astro-server/util.js'; import { isBuildableCSSRequest } from '../../../vite-plugin-astro-server/util.js';
@ -93,7 +91,7 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
if (new URL(pageInfo.id, 'file://').searchParams.has(PROPAGATED_ASSET_FLAG)) { if (new URL(pageInfo.id, 'file://').searchParams.has(PROPAGATED_ASSET_FLAG)) {
// Split delayed assets to separate modules // Split delayed assets to separate modules
// so they can be injected where needed // so they can be injected where needed
const chunkId = createNameHash(id, [id]); const chunkId = assetName.createNameHash(id, [id]);
internals.cssModuleToChunkIdMap.set(id, chunkId); internals.cssModuleToChunkIdMap.set(id, chunkId);
return chunkId; return chunkId;
} }
@ -272,17 +270,6 @@ function rollupPluginAstroBuildCSS(options: PluginOptions): VitePlugin[] {
/***** UTILITY FUNCTIONS *****/ /***** UTILITY FUNCTIONS *****/
function createNameHash(baseId: string, hashIds: string[]): string {
const baseName = baseId ? npath.parse(baseId).name : 'index';
const hash = crypto.createHash('sha256');
for (const id of hashIds) {
hash.update(id, 'utf-8');
}
const h = hash.digest('hex').slice(0, 8);
const proposedName = baseName + '.' + h;
return proposedName;
}
function* getParentClientOnlys( function* getParentClientOnlys(
id: string, id: string,
ctx: { getModuleInfo: GetModuleInfo }, ctx: { getModuleInfo: GetModuleInfo },