From ae59f60421ed49a029f58db702250ac0ba3c966e Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:55:37 -0700 Subject: [PATCH] perf: hoist vite asset declarations to module block --- .changeset/friendly-wasps-return.md | 5 ++ packages/enhanced-img/src/preprocessor.js | 64 +++++++++++++++++------ packages/enhanced-img/test/Output.svelte | 12 +++-- 3 files changed, 61 insertions(+), 20 deletions(-) create mode 100644 .changeset/friendly-wasps-return.md diff --git a/.changeset/friendly-wasps-return.md b/.changeset/friendly-wasps-return.md new file mode 100644 index 000000000000..c2861781db9c --- /dev/null +++ b/.changeset/friendly-wasps-return.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/enhanced-img': patch +--- + +perf: hoist vite asset declarations to module block diff --git a/packages/enhanced-img/src/preprocessor.js b/packages/enhanced-img/src/preprocessor.js index aad4b6d955bf..0adf1306a9dd 100644 --- a/packages/enhanced-img/src/preprocessor.js +++ b/packages/enhanced-img/src/preprocessor.js @@ -5,8 +5,6 @@ import MagicString from 'magic-string'; import { asyncWalk } from 'estree-walker'; import { parse } from 'svelte-parse-markup'; -const ASSET_PREFIX = '___ASSET___'; - // TODO: expose this in vite-imagetools rather than duplicating it const OPTIMIZABLE = /^[^?]+\.(avif|heif|gif|jpeg|jpg|png|tiff|webp)(\?.*)?$/; @@ -35,11 +33,20 @@ export function image(opts) { const s = new MagicString(content); const ast = parse(content, { filename }); - // Import path to import name - // e.g. ./foo.png => ___ASSET___0 - /** @type {Map} */ + /** + * Import path to import name + * e.g. ./foo.png => __IMPORTED_ASSET_0__ + * @type {Map} + */ const imports = new Map(); + /** + * Vite name to declaration name + * e.g. __VITE_ASSET_0__ => __DECLARED_ASSET_0__ + * @type {Map} + */ + const consts = new Map(); + /** * @param {import('svelte/types/compiler/interfaces').TemplateNode} node * @param {{ type: string, start: number, end: number, raw: string }} src_attribute @@ -94,10 +101,10 @@ 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, img_to_picture(consts, content, node, image)); } else { - // e.g. => - const name = ASSET_PREFIX + imports.size; + // e.g. => + const name = '__IMPORTED_ASSET_' + imports.size + '__'; const { start, end } = src_attribute; // update src with reference to imported asset s.update( @@ -131,15 +138,28 @@ export function image(opts) { // add imports if (imports.size) { - let import_text = ''; + let text = ''; for (const [path, import_name] of imports.entries()) { - import_text += `import ${import_name} from "${path}";`; + text += `import ${import_name} from "${path}";`; } if (ast.instance) { // @ts-ignore - s.appendLeft(ast.instance.content.start, import_text); + s.appendLeft(ast.instance.content.start, text); + } else { + s.prepend(``); + } + } + + if (consts.size) { + let text = ''; + for (const [vite_name, declaration_name] of consts.entries()) { + text += `\tconst ${declaration_name} = "${vite_name}";\n`; + } + if (ast.module) { + // @ts-ignore + s.appendLeft(ast.module.content.start, text); } else { - s.append(``); + s.prepend(`\n`); } } @@ -264,11 +284,12 @@ function stringToNumber(param) { } /** + * @param {Map} consts * @param {string} content * @param {import('svelte/types/compiler/interfaces').TemplateNode} node * @param {import('vite-imagetools').Picture} image */ -function img_to_picture(content, node, image) { +function img_to_picture(consts, content, node, image) { /** @type {Array} attributes */ const attributes = node.attributes; const index = attributes.findIndex((attribute) => attribute.name === 'sizes'); @@ -281,11 +302,11 @@ function img_to_picture(content, node, image) { let res = ''; for (const [format, srcset] of Object.entries(image.sources)) { - res += ``; + res += ``; } res += ``; @@ -294,10 +315,19 @@ function img_to_picture(content, node, image) { } /** + * @param {Map} consts * @param {string} src */ -function to_value(src) { - return src.startsWith('__VITE_ASSET__') ? `{"${src}"}` : `"${src}"`; +function to_value(consts, src) { + if (src.startsWith('__VITE_ASSET__')) { + let var_name = consts.get(src); + if (!var_name) { + var_name = '__DECLARED_ASSET_' + consts.size + '__'; + consts.set(src, var_name); + } + return `{${var_name}}`; + } + return `"${src}"`; } /** diff --git a/packages/enhanced-img/test/Output.svelte b/packages/enhanced-img/test/Output.svelte index 8e5ac49d5da1..9f3f88f25efe 100644 --- a/packages/enhanced-img/test/Output.svelte +++ b/packages/enhanced-img/test/Output.svelte @@ -1,5 +1,11 @@ +