Skip to content

Commit

Permalink
refactor(assets): Move generation logic out of internal.ts (#7102)
Browse files Browse the repository at this point in the history
  • Loading branch information
Princesseuh committed May 16, 2023
1 parent 6cbe5e7 commit 4516d7b
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 125 deletions.
5 changes: 5 additions & 0 deletions .changeset/brown-goats-serve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fix image services not being usable on Edge runtimes
126 changes: 126 additions & 0 deletions packages/astro/src/assets/generate.ts
Original file line number Diff line number Diff line change
@@ -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();
}
125 changes: 1 addition & 124 deletions packages/astro/src/assets/internal.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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),
},
};
}
2 changes: 1 addition & 1 deletion packages/astro/src/core/build/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 4516d7b

Please sign in to comment.