summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/rich-dolphins-teach.md5
-rw-r--r--packages/integrations/image/package.json1
-rw-r--r--packages/integrations/image/src/build/ssg.ts26
-rw-r--r--pnpm-lock.yaml6
4 files changed, 31 insertions, 7 deletions
diff --git a/.changeset/rich-dolphins-teach.md b/.changeset/rich-dolphins-teach.md
new file mode 100644
index 000000000..a9bbf7de9
--- /dev/null
+++ b/.changeset/rich-dolphins-teach.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/image': patch
+---
+
+Parallelize image transforms
diff --git a/packages/integrations/image/package.json b/packages/integrations/image/package.json
index 045569767..fb1aaa67b 100644
--- a/packages/integrations/image/package.json
+++ b/packages/integrations/image/package.json
@@ -40,6 +40,7 @@
"test": "mocha --exit --timeout 20000 test"
},
"dependencies": {
+ "@altano/tiny-async-pool": "^1.0.2",
"image-size": "^1.0.2",
"magic-string": "^0.25.9",
"mime": "^3.0.0",
diff --git a/packages/integrations/image/src/build/ssg.ts b/packages/integrations/image/src/build/ssg.ts
index 4602ef935..6ee167ce6 100644
--- a/packages/integrations/image/src/build/ssg.ts
+++ b/packages/integrations/image/src/build/ssg.ts
@@ -7,6 +7,8 @@ import type { SSRImageService, TransformOptions } from '../loaders/index.js';
import { loadLocalImage, loadRemoteImage } from '../utils/images.js';
import { debug, info, LoggerLevel, warn } from '../utils/logger.js';
import { isRemoteImage } from '../utils/paths.js';
+import OS from 'node:os';
+import { doWork } from '@altano/tiny-async-pool';
function getTimeStat(timeStart: number, timeEnd: number) {
const buildTime = timeEnd - timeStart;
@@ -23,19 +25,26 @@ export interface SSGBuildParams {
export async function ssgBuild({ loader, staticImages, config, outDir, logLevel }: SSGBuildParams) {
const timer = performance.now();
+ const cpuCount = OS.cpus().length;
info({
level: logLevel,
prefix: false,
message: `${bgGreen(
- black(` optimizing ${staticImages.size} image${staticImages.size > 1 ? 's' : ''} `)
+ black(
+ ` optimizing ${staticImages.size} image${
+ staticImages.size > 1 ? 's' : ''
+ } in batches of ${cpuCount} `
+ )
)}`,
});
const inputFiles = new Set<string>();
- // process transforms one original image file at a time
- for (let [src, transformsMap] of staticImages) {
+ async function processStaticImage([src, transformsMap]: [
+ string,
+ Map<string, TransformOptions>
+ ]): Promise<void> {
let inputFile: string | undefined = undefined;
let inputBuffer: Buffer | undefined = undefined;
@@ -60,15 +69,15 @@ export async function ssgBuild({ loader, staticImages, config, outDir, logLevel
if (!inputBuffer) {
// eslint-disable-next-line no-console
warn({ level: logLevel, message: `"${src}" image could not be fetched` });
- continue;
+ return;
}
const transforms = Array.from(transformsMap.entries());
- debug({ level: logLevel, prefix: false, message: `${green('▶')} ${src}` });
+ debug({ level: logLevel, prefix: false, message: `${green('▶')} transforming ${src}` });
let timeStart = performance.now();
- // process each transformed versiono of the
+ // process each transformed version
for (const [filename, transform] of transforms) {
timeStart = performance.now();
let outputFile: string;
@@ -92,11 +101,14 @@ export async function ssgBuild({ loader, staticImages, config, outDir, logLevel
debug({
level: logLevel,
prefix: false,
- message: ` ${cyan('└─')} ${dim(pathRelative)} ${dim(timeIncrease)}`,
+ message: ` ${cyan('created')} ${dim(pathRelative)} ${dim(timeIncrease)}`,
});
}
}
+ // transform each original image file in batches
+ await doWork(cpuCount, staticImages, processStaticImage);
+
info({
level: logLevel,
prefix: false,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ad1c1c3d0..35cea9fc7 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2214,6 +2214,7 @@ importers:
packages/integrations/image:
specifiers:
+ '@altano/tiny-async-pool': ^1.0.2
'@types/sharp': ^0.30.5
astro: workspace:*
astro-scripts: workspace:*
@@ -2223,6 +2224,7 @@ importers:
mime: ^3.0.0
sharp: ^0.30.6
dependencies:
+ '@altano/tiny-async-pool': 1.0.2
image-size: 1.0.2
magic-string: 0.25.9
mime: 3.0.0
@@ -3155,6 +3157,10 @@ packages:
'@algolia/requester-common': 4.14.2
dev: false
+ /@altano/tiny-async-pool/1.0.2:
+ resolution: {integrity: sha512-qQzaI0TBUPdpjZ3qo5b2ziQY9MSNpbziH2ZrE5lvtUZL+kn9GwVuVJwoOubaoNkeDB+rqEefnpu1k+oMpOCYiw==}
+ dev: false
+
/@ampproject/remapping/2.2.0:
resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==}
engines: {node: '>=6.0.0'}