From 7cf670319441b43bdd60791b8260ddfd7715913a Mon Sep 17 00:00:00 2001 From: Joel Kuzmarski Date: Thu, 14 Mar 2024 03:45:30 -0500 Subject: [PATCH] Example of how to add support for Vercel to enhanced-img --- packages/enhanced-img/src/index.js | 34 +++++++---- packages/enhanced-img/src/preprocessor.js | 61 ++++++++++++++++++- packages/enhanced-img/types/index.d.ts | 2 +- .../src/routes/home/Hero.svelte | 2 +- sites/kit.svelte.dev/svelte.config.js | 8 ++- sites/kit.svelte.dev/vite.config.js | 4 +- 6 files changed, 94 insertions(+), 17 deletions(-) diff --git a/packages/enhanced-img/src/index.js b/packages/enhanced-img/src/index.js index bbdac4d9b5d7..17c364a6ba2a 100644 --- a/packages/enhanced-img/src/index.js +++ b/packages/enhanced-img/src/index.js @@ -3,26 +3,29 @@ import { imagetools } from 'vite-imagetools'; import { image } from './preprocessor.js'; /** + * @param {Object} options * @returns {Promise} */ -export async function enhancedImages() { +export async function enhancedImages(options) { const imagetools_instance = await imagetools_plugin(); return !process.versions.webcontainer - ? [image_plugin(imagetools_instance), imagetools_instance] + ? [image_plugin(imagetools_instance, options), imagetools_instance] : []; } /** * Creates the Svelte image plugin which provides the preprocessor. * @param {import('vite').Plugin} imagetools_plugin + * @param {{vercel_sizes: number[]}} options * @returns {import('vite').Plugin} */ -function image_plugin(imagetools_plugin) { +function image_plugin(imagetools_plugin, options) { /** * @type {{ * plugin_context: import('vite').Rollup.PluginContext * vite_config: import('vite').ResolvedConfig * imagetools_plugin: import('vite').Plugin + * vercel_sizes: number[] * }} */ const opts = { @@ -30,7 +33,8 @@ function image_plugin(imagetools_plugin) { plugin_context: undefined, // @ts-expect-error populated when build starts so we cheat on type vite_config: undefined, - imagetools_plugin + imagetools_plugin, + vercel_sizes: options.vercel_sizes }; const preprocessor = image(opts); @@ -73,13 +77,21 @@ async function imagetools_plugin() { return new URLSearchParams(); } - const { widths, kind } = get_widths(width, qs.get('imgSizes')); - return new URLSearchParams({ - as: 'picture', - format: `avif;webp;${fallback[path.extname(pathname)] ?? 'png'}`, - w: widths.join(';'), - ...(kind === 'x' && !qs.has('w') && { basePixels: widths[0].toString() }) - }); + if (qs.get('cdn')) { + return new URLSearchParams({ + as: 'picture', + format: `${fallback[path.extname(pathname)] ?? 'png'}`, + w: width.toString() + }); + } else { + const { widths, kind } = get_widths(width, qs.get('imgSizes')); + return new URLSearchParams({ + as: 'picture', + format: `avif;webp;${fallback[path.extname(pathname)] ?? 'png'}`, + w: widths.join(';'), + ...(kind === 'x' && !qs.has('w') && { basePixels: widths[0].toString() }) + }); + } }, namedExports: false }; diff --git a/packages/enhanced-img/src/preprocessor.js b/packages/enhanced-img/src/preprocessor.js index 0575f88c5259..df8d671df9bd 100644 --- a/packages/enhanced-img/src/preprocessor.js +++ b/packages/enhanced-img/src/preprocessor.js @@ -15,6 +15,7 @@ const OPTIMIZABLE = /^[^?]+\.(avif|heif|gif|jpeg|jpg|png|tiff|webp)(\?.*)?$/; * plugin_context: import('vite').Rollup.PluginContext * vite_config: import('vite').ResolvedConfig * imagetools_plugin: import('vite').Plugin + * vercel_sizes: number[] * }} opts * @returns {import('svelte/types/compiler/preprocess').PreprocessorGroup} */ @@ -90,7 +91,13 @@ export function image(opts) { image = await process(resolved_id, opts); images.set(resolved_id, image); } - s.update(node.start, node.end, img_to_picture(content, node, image)); + s.update( + node.start, + node.end, + url.includes('cdn=vercel') + ? img_to_vercel(content, node, image, opts.vercel_sizes, opts.vite_config.env.DEV) + : img_to_picture(content, node, image) + ); } else { // e.g. => const name = ASSET_PREFIX + imports.size; @@ -175,7 +182,9 @@ async function process(resolved_id, opts) { throw new Error(`Could not load ${resolved_id}`); } const code = typeof module_info === 'string' ? module_info : module_info.code; - return parseObject(code.replace('export default', '').replace(/;$/, '').trim()); + return parseObject( + code.replace('export default', '').replace('sources:{},', '').replace(/;$/, '').trim() + ); } /** @@ -293,6 +302,54 @@ function img_to_picture(content, node, image) { return res; } +/** + * @param {string} content + * @param {import('svelte/types/compiler/interfaces').TemplateNode} node + * @param {import('vite-imagetools').Picture} image + * @param {number[]} sizes + * @param {boolean} isDev + */ +function img_to_vercel(content, node, image, sizes, isDev) { + /** @type {Array} attributes */ + const attributes = node.attributes; + + let res = ''; + // Need to handle src differently when using either Vite's renderBuiltUrl or relative base path in Vite. + // See https://github.com/vitejs/vite/blob/b93dfe3e08f56cafe2e549efd80285a12a3dc2f0/packages/vite/src/node/plugins/asset.ts#L132 + const src = + image.img.src.startsWith('"+') && image.img.src.endsWith('+"') + ? `{"${image.img.src.substring(2, image.img.src.length - 2)}"}` // @TODO: Does this affect us??? + : `"${image.img.src}"`; + + res += ``; + + return res; +} + +/** + * @param {number[]} widths + */ +function srcset_vercel(src = '', widths, quality = 100, isDev = false) { + return widths + .slice() + .sort((a, b) => a - b) + .map((width) => { + let url = `/_vercel/image?url=${encodeURIComponent(src)}&w=${width}&q=${quality}`; + return `${isDev ? src : url} ${width}w`; + }) + .join(', '); +} + /** * For images like `` * @param {string} content diff --git a/packages/enhanced-img/types/index.d.ts b/packages/enhanced-img/types/index.d.ts index 05bf05b76a32..8d401f5875be 100644 --- a/packages/enhanced-img/types/index.d.ts +++ b/packages/enhanced-img/types/index.d.ts @@ -9,4 +9,4 @@ declare module 'svelte/elements' { } } -export function enhancedImages(): Promise; +export function enhancedImages(options: { vercel_sizes: number[] }): Promise; diff --git a/sites/kit.svelte.dev/src/routes/home/Hero.svelte b/sites/kit.svelte.dev/src/routes/home/Hero.svelte index 11000359ee61..c5361b81cc07 100644 --- a/sites/kit.svelte.dev/src/routes/home/Hero.svelte +++ b/sites/kit.svelte.dev/src/routes/home/Hero.svelte @@ -16,7 +16,7 @@