Skip to content

Commit

Permalink
Allow image-pool to be used as its own Worker (#5317)
Browse files Browse the repository at this point in the history
* Allow image-pool to be used as its own Worker

* Adding a changeset

* fix image tests

* update picture tests

* Pass the current URL
  • Loading branch information
matthewp committed Nov 8, 2022
1 parent a79a37c commit d701ae0
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-beers-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/image': patch
---

Fixes use of image worker pool in SSR environments
11 changes: 11 additions & 0 deletions packages/integrations/image/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ export { getPicture } from './lib/get-picture.js';

const PKG_NAME = '@astrojs/image';
const ROUTE_PATTERN = '/_image';
const UNSUPPORTED_ADAPTERS = new Set([
'@astrojs/cloudflare',
'@astrojs/deno',
'@astrojs/netlify/edge-functions',
'@astrojs/vercel/edge'
]);

interface BuildConfig {
client: URL;
Expand Down Expand Up @@ -100,6 +106,11 @@ export default function integration(options: IntegrationOptions = {}): AstroInte
_buildConfig = config.build;
},
'astro:build:start': ({ buildConfig }) => {
const adapterName = _config.adapter?.name;
if(adapterName && UNSUPPORTED_ADAPTERS.has(adapterName)) {
throw new Error(`@astrojs/image is not supported with the ${adapterName} adapter. Please choose a Node.js compatible adapter.`);
}

// Backwards compat
if (needsBuildConfig) {
_buildConfig = buildConfig;
Expand Down
5 changes: 3 additions & 2 deletions packages/integrations/image/src/loaders/squoosh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import { red } from 'kleur/colors';
import { error } from '../utils/logger.js';
import { metadata } from '../utils/metadata.js';
import { isRemoteImage } from '../utils/paths.js';
import { processBuffer } from '../vendor/squoosh/image-pool.js';
import type { Operation } from '../vendor/squoosh/image.js';
import type { OutputFormat, TransformOptions } from './index.js';
import { BaseSSRService } from './index.js';

const imagePoolModulePromise = import('../vendor/squoosh/image-pool.js');

class SquooshService extends BaseSSRService {
async processAvif(image: any, transform: TransformOptions) {
const encodeOptions = transform.quality
Expand Down Expand Up @@ -112,7 +113,7 @@ class SquooshService extends BaseSSRService {
});
throw new Error(`Unknown image output: "${transform.format}" used for ${transform.src}`);
}

const { processBuffer } = await imagePoolModulePromise;
const data = await processBuffer(inputBuffer, operations, transform.format, transform.quality);

return {
Expand Down
3 changes: 2 additions & 1 deletion packages/integrations/image/src/vendor/squoosh/image-pool.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isMainThread } from 'node:worker_threads';
import { cpus } from 'os';
import { fileURLToPath } from 'url';
import type { OutputFormat } from '../../loaders/index.js';
import execOnce from '../../utils/execOnce.js';
import WorkerPool from '../../utils/workerPool.js';
Expand All @@ -12,7 +13,7 @@ const getWorker = execOnce(
// There will be at most 7 workers needed since each worker will take
// at least 1 operation type.
Math.max(1, Math.min(cpus().length - 1, 7)),
'./node_modules/@astrojs/image/dist/vendor/squoosh/image-pool.js'
fileURLToPath(import.meta.url)
);
}
)
Expand Down
21 changes: 21 additions & 0 deletions packages/integrations/image/src/vite-plugin-astro-image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,27 @@ export function createPlugin(config: AstroConfig, options: Required<IntegrationO
return next();
});
},
outputOptions(outputOptions) {
if(resolvedConfig.build.ssr) {
// Build the image-pool chunk to the top-level and not inside of a chunks/
// folder. This is because the wasm is built at the top-level and this makes
// it accessible from the pool worker.
const chunkFileNames = outputOptions.chunkFileNames;
outputOptions.chunkFileNames = (chunk) => {
for(const name of Object.keys(chunk.modules)) {
if(name.endsWith('vendor/squoosh/image-pool.js')) {
return '[name].[hash].mjs';
}
}

if(typeof chunkFileNames === 'function') {
return chunkFileNames.call(this, chunk);
}

return chunkFileNames!;
};
}
},
async renderChunk(code) {
const assetUrlRE = /__ASTRO_IMAGE_ASSET__([a-z\d]{8})__(?:_(.*?)__)?/g;

Expand Down

0 comments on commit d701ae0

Please sign in to comment.