Fix multiple images being generated for the same image (#6710)
* fix(images): Fix multiple calls to same image generating multiple images * chore: changeset
This commit is contained in:
parent
b1b9b1390f
commit
a0bdf4ce2f
6 changed files with 28 additions and 15 deletions
5
.changeset/new-coats-check.md
Normal file
5
.changeset/new-coats-check.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix multiple Image / getImage calls with the same image causing multiple duplicate images to be generated
|
|
@ -79,7 +79,9 @@ export async function getImage(options: ImageTransform): Promise<GetImageResult>
|
|||
};
|
||||
}
|
||||
|
||||
export function getStaticImageList(): Iterable<[ImageTransform, string]> {
|
||||
export function getStaticImageList(): Iterable<
|
||||
[string, { path: string; options: ImageTransform }]
|
||||
> {
|
||||
if (!globalThis?.astroAsset?.staticImages) {
|
||||
return [];
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ declare global {
|
|||
var astroAsset: {
|
||||
imageService?: ImageService;
|
||||
addStaticImage?: ((options: ImageTransform) => string) | undefined;
|
||||
staticImages?: Map<ImageTransform, string>;
|
||||
staticImages?: Map<string, { path: string; options: ImageTransform }>;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import { shorthash } from '../../runtime/server/shorthash.js';
|
|||
import { isESMImportedImage } from '../internal.js';
|
||||
import type { ImageTransform } from '../types.js';
|
||||
|
||||
export function propsToFilename(transform: ImageTransform, imageService: string) {
|
||||
export function propsToFilename(transform: ImageTransform, hash: string) {
|
||||
if (!isESMImportedImage(transform.src)) {
|
||||
return transform.src;
|
||||
}
|
||||
|
@ -12,9 +12,13 @@ export function propsToFilename(transform: ImageTransform, imageService: string)
|
|||
let filename = removeQueryString(transform.src.src);
|
||||
const ext = extname(filename);
|
||||
filename = basename(filename, ext);
|
||||
const outputExt = transform.format ? `.${transform.format}` : ext;
|
||||
return `/${filename}_${hash}${outputExt}`;
|
||||
}
|
||||
|
||||
export function hashTransform(transform: ImageTransform, imageService: string) {
|
||||
// take everything from transform except alt, which is not used in the hash
|
||||
const { alt, ...rest } = transform;
|
||||
const hashFields = { ...rest, imageService };
|
||||
const outputExt = transform.format ? `.${transform.format}` : ext;
|
||||
return `/${filename}_${shorthash(JSON.stringify(hashFields))}${outputExt}`;
|
||||
return shorthash(JSON.stringify(hashFields));
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import { copyWasmFiles } from './services/vendor/squoosh/copy-wasm.js';
|
|||
import { emitESMImage } from './utils/emitAsset.js';
|
||||
import { imageMetadata } from './utils/metadata.js';
|
||||
import { getOrigQueryParams } from './utils/queryParams.js';
|
||||
import { propsToFilename } from './utils/transformToPath.js';
|
||||
import { hashTransform, propsToFilename } from './utils/transformToPath.js';
|
||||
|
||||
const resolvedVirtualModuleId = '\0' + VIRTUAL_MODULE_ID;
|
||||
|
||||
|
@ -153,12 +153,17 @@ export default function assets({
|
|||
|
||||
globalThis.astroAsset.addStaticImage = (options) => {
|
||||
if (!globalThis.astroAsset.staticImages) {
|
||||
globalThis.astroAsset.staticImages = new Map<ImageTransform, string>();
|
||||
globalThis.astroAsset.staticImages = new Map<
|
||||
string,
|
||||
{ path: string; options: ImageTransform }
|
||||
>();
|
||||
}
|
||||
|
||||
const hash = hashTransform(options, settings.config.image.service);
|
||||
|
||||
let filePath: string;
|
||||
if (globalThis.astroAsset.staticImages.has(options)) {
|
||||
filePath = globalThis.astroAsset.staticImages.get(options)!;
|
||||
if (globalThis.astroAsset.staticImages.has(hash)) {
|
||||
filePath = globalThis.astroAsset.staticImages.get(hash)!.path;
|
||||
} else {
|
||||
// If the image is not imported, we can return the path as-is, since static references
|
||||
// should only point ot valid paths for builds or remote images
|
||||
|
@ -167,12 +172,9 @@ export default function assets({
|
|||
}
|
||||
|
||||
filePath = prependForwardSlash(
|
||||
joinPaths(
|
||||
settings.config.build.assets,
|
||||
propsToFilename(options, settings.config.image.service)
|
||||
)
|
||||
joinPaths(settings.config.build.assets, propsToFilename(options, hash))
|
||||
);
|
||||
globalThis.astroAsset.staticImages.set(options, filePath);
|
||||
globalThis.astroAsset.staticImages.set(hash, { path: filePath, options: options });
|
||||
}
|
||||
|
||||
return prependForwardSlash(joinPaths(settings.config.base, filePath));
|
||||
|
|
|
@ -108,7 +108,7 @@ export async function generatePages(opts: StaticBuildOptions, internals: BuildIn
|
|||
if (opts.settings.config.experimental.assets) {
|
||||
info(opts.logging, null, `\n${bgGreen(black(` generating optimized images `))}`);
|
||||
for (const imageData of getStaticImageList()) {
|
||||
await generateImage(opts, imageData[0], imageData[1]);
|
||||
await generateImage(opts, imageData[1].options, imageData[1].path);
|
||||
}
|
||||
delete globalThis.astroAsset.addStaticImage;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue