mirror of
https://github.com/withastro/astro.git
synced 2025-01-27 22:19:04 -05:00
refactor(assets): Move generation logic out of internal.ts (#7102)
This commit is contained in:
parent
6cbe5e7472
commit
4516d7b22c
4 changed files with 133 additions and 125 deletions
5
.changeset/brown-goats-serve.md
Normal file
5
.changeset/brown-goats-serve.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix image services not being usable on Edge runtimes
|
126
packages/astro/src/assets/generate.ts
Normal file
126
packages/astro/src/assets/generate.ts
Normal file
|
@ -0,0 +1,126 @@
|
|||
import fs from 'node:fs';
|
||||
import { basename, join } from 'node:path/posix';
|
||||
import type { StaticBuildOptions } from '../core/build/types.js';
|
||||
import { warn } from '../core/logger/core.js';
|
||||
import { prependForwardSlash } from '../core/path.js';
|
||||
import { getConfiguredImageService, isESMImportedImage } from './internal.js';
|
||||
import type { LocalImageService } from './services/service.js';
|
||||
import type { ImageTransform } from './types.js';
|
||||
|
||||
interface GenerationDataUncached {
|
||||
cached: false;
|
||||
weight: {
|
||||
before: number;
|
||||
after: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface GenerationDataCached {
|
||||
cached: true;
|
||||
}
|
||||
|
||||
type GenerationData = GenerationDataUncached | GenerationDataCached;
|
||||
|
||||
export async function generateImage(
|
||||
buildOpts: StaticBuildOptions,
|
||||
options: ImageTransform,
|
||||
filepath: string
|
||||
): Promise<GenerationData | undefined> {
|
||||
if (!isESMImportedImage(options.src)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let useCache = true;
|
||||
const assetsCacheDir = new URL('assets/', buildOpts.settings.config.cacheDir);
|
||||
|
||||
// Ensure that the cache directory exists
|
||||
try {
|
||||
await fs.promises.mkdir(assetsCacheDir, { recursive: true });
|
||||
} catch (err) {
|
||||
warn(
|
||||
buildOpts.logging,
|
||||
'astro:assets',
|
||||
`An error was encountered while creating the cache directory. Proceeding without caching. Error: ${err}`
|
||||
);
|
||||
useCache = false;
|
||||
}
|
||||
|
||||
let serverRoot: URL, clientRoot: URL;
|
||||
if (buildOpts.settings.config.output === 'server') {
|
||||
serverRoot = buildOpts.settings.config.build.server;
|
||||
clientRoot = buildOpts.settings.config.build.client;
|
||||
} else {
|
||||
serverRoot = buildOpts.settings.config.outDir;
|
||||
clientRoot = buildOpts.settings.config.outDir;
|
||||
}
|
||||
|
||||
const finalFileURL = new URL('.' + filepath, clientRoot);
|
||||
const finalFolderURL = new URL('./', finalFileURL);
|
||||
const cachedFileURL = new URL(basename(filepath), assetsCacheDir);
|
||||
|
||||
try {
|
||||
await fs.promises.copyFile(cachedFileURL, finalFileURL);
|
||||
|
||||
return {
|
||||
cached: true,
|
||||
};
|
||||
} catch (e) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// The original file's path (the `src` attribute of the ESM imported image passed by the user)
|
||||
const originalImagePath = options.src.src;
|
||||
|
||||
const fileData = await fs.promises.readFile(
|
||||
new URL(
|
||||
'.' +
|
||||
prependForwardSlash(
|
||||
join(buildOpts.settings.config.build.assets, basename(originalImagePath))
|
||||
),
|
||||
serverRoot
|
||||
)
|
||||
);
|
||||
|
||||
const imageService = (await getConfiguredImageService()) as LocalImageService;
|
||||
const resultData = await imageService.transform(
|
||||
fileData,
|
||||
{ ...options, src: originalImagePath },
|
||||
buildOpts.settings.config.image.service.config
|
||||
);
|
||||
|
||||
await fs.promises.mkdir(finalFolderURL, { recursive: true });
|
||||
|
||||
if (useCache) {
|
||||
try {
|
||||
await fs.promises.writeFile(cachedFileURL, resultData.data);
|
||||
await fs.promises.copyFile(cachedFileURL, finalFileURL);
|
||||
} catch (e) {
|
||||
warn(
|
||||
buildOpts.logging,
|
||||
'astro:assets',
|
||||
`An error was encountered while creating the cache directory. Proceeding without caching. Error: ${e}`
|
||||
);
|
||||
await fs.promises.writeFile(finalFileURL, resultData.data);
|
||||
}
|
||||
} else {
|
||||
await fs.promises.writeFile(finalFileURL, resultData.data);
|
||||
}
|
||||
|
||||
return {
|
||||
cached: false,
|
||||
weight: {
|
||||
before: Math.trunc(fileData.byteLength / 1024),
|
||||
after: Math.trunc(resultData.data.byteLength / 1024),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function getStaticImageList(): Iterable<
|
||||
[string, { path: string; options: ImageTransform }]
|
||||
> {
|
||||
if (!globalThis?.astroAsset?.staticImages) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return globalThis.astroAsset.staticImages?.entries();
|
||||
}
|
|
@ -1,10 +1,5 @@
|
|||
import fs from 'node:fs';
|
||||
import { basename, join } from 'node:path/posix';
|
||||
import type { StaticBuildOptions } from '../core/build/types.js';
|
||||
import { AstroError, AstroErrorData } from '../core/errors/index.js';
|
||||
import { warn } from '../core/logger/core.js';
|
||||
import { prependForwardSlash } from '../core/path.js';
|
||||
import { isLocalService, type ImageService, type LocalImageService } from './services/service.js';
|
||||
import { isLocalService, type ImageService } from './services/service.js';
|
||||
import type { GetImageResult, ImageMetadata, ImageTransform } from './types.js';
|
||||
|
||||
export function isESMImportedImage(src: ImageMetadata | string): src is ImageMetadata {
|
||||
|
@ -63,121 +58,3 @@ export async function getImage(
|
|||
: {},
|
||||
};
|
||||
}
|
||||
|
||||
export function getStaticImageList(): Iterable<
|
||||
[string, { path: string; options: ImageTransform }]
|
||||
> {
|
||||
if (!globalThis?.astroAsset?.staticImages) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return globalThis.astroAsset.staticImages?.entries();
|
||||
}
|
||||
|
||||
interface GenerationDataUncached {
|
||||
cached: false;
|
||||
weight: {
|
||||
before: number;
|
||||
after: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface GenerationDataCached {
|
||||
cached: true;
|
||||
}
|
||||
|
||||
type GenerationData = GenerationDataUncached | GenerationDataCached;
|
||||
|
||||
export async function generateImage(
|
||||
buildOpts: StaticBuildOptions,
|
||||
options: ImageTransform,
|
||||
filepath: string
|
||||
): Promise<GenerationData | undefined> {
|
||||
if (!isESMImportedImage(options.src)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let useCache = true;
|
||||
const assetsCacheDir = new URL('assets/', buildOpts.settings.config.cacheDir);
|
||||
|
||||
// Ensure that the cache directory exists
|
||||
try {
|
||||
await fs.promises.mkdir(assetsCacheDir, { recursive: true });
|
||||
} catch (err) {
|
||||
warn(
|
||||
buildOpts.logging,
|
||||
'astro:assets',
|
||||
`An error was encountered while creating the cache directory. Proceeding without caching. Error: ${err}`
|
||||
);
|
||||
useCache = false;
|
||||
}
|
||||
|
||||
let serverRoot: URL, clientRoot: URL;
|
||||
if (buildOpts.settings.config.output === 'server') {
|
||||
serverRoot = buildOpts.settings.config.build.server;
|
||||
clientRoot = buildOpts.settings.config.build.client;
|
||||
} else {
|
||||
serverRoot = buildOpts.settings.config.outDir;
|
||||
clientRoot = buildOpts.settings.config.outDir;
|
||||
}
|
||||
|
||||
const finalFileURL = new URL('.' + filepath, clientRoot);
|
||||
const finalFolderURL = new URL('./', finalFileURL);
|
||||
const cachedFileURL = new URL(basename(filepath), assetsCacheDir);
|
||||
|
||||
try {
|
||||
await fs.promises.copyFile(cachedFileURL, finalFileURL);
|
||||
|
||||
return {
|
||||
cached: true,
|
||||
};
|
||||
} catch (e) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// The original file's path (the `src` attribute of the ESM imported image passed by the user)
|
||||
const originalImagePath = options.src.src;
|
||||
|
||||
const fileData = await fs.promises.readFile(
|
||||
new URL(
|
||||
'.' +
|
||||
prependForwardSlash(
|
||||
join(buildOpts.settings.config.build.assets, basename(originalImagePath))
|
||||
),
|
||||
serverRoot
|
||||
)
|
||||
);
|
||||
|
||||
const imageService = (await getConfiguredImageService()) as LocalImageService;
|
||||
const resultData = await imageService.transform(
|
||||
fileData,
|
||||
{ ...options, src: originalImagePath },
|
||||
buildOpts.settings.config.image.service.config
|
||||
);
|
||||
|
||||
await fs.promises.mkdir(finalFolderURL, { recursive: true });
|
||||
|
||||
if (useCache) {
|
||||
try {
|
||||
await fs.promises.writeFile(cachedFileURL, resultData.data);
|
||||
await fs.promises.copyFile(cachedFileURL, finalFileURL);
|
||||
} catch (e) {
|
||||
warn(
|
||||
buildOpts.logging,
|
||||
'astro:assets',
|
||||
`An error was encountered while creating the cache directory. Proceeding without caching. Error: ${e}`
|
||||
);
|
||||
await fs.promises.writeFile(finalFileURL, resultData.data);
|
||||
}
|
||||
} else {
|
||||
await fs.promises.writeFile(finalFileURL, resultData.data);
|
||||
}
|
||||
|
||||
return {
|
||||
cached: false,
|
||||
weight: {
|
||||
before: Math.trunc(fileData.byteLength / 1024),
|
||||
after: Math.trunc(resultData.data.byteLength / 1024),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import type {
|
|||
import {
|
||||
generateImage as generateImageInternal,
|
||||
getStaticImageList,
|
||||
} from '../../assets/internal.js';
|
||||
} from '../../assets/generate.js';
|
||||
import { hasPrerenderedPages, type BuildInternals } from '../../core/build/internal.js';
|
||||
import {
|
||||
prependForwardSlash,
|
||||
|
|
Loading…
Add table
Reference in a new issue