From 2884827febf60c2ce61888f4cbf724b12eaf8286 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 4 Nov 2025 13:58:12 +0000 Subject: [PATCH 1/2] perf(nuxt-img): call `decode` before swapping from placeholder --- src/runtime/components/NuxtImg.vue | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/runtime/components/NuxtImg.vue b/src/runtime/components/NuxtImg.vue index 5172ca13e..53ecad0eb 100644 --- a/src/runtime/components/NuxtImg.vue +++ b/src/runtime/components/NuxtImg.vue @@ -146,13 +146,28 @@ onMounted(() => { img.srcset = sizes.value.srcset } - img.onload = (event) => { - placeholderLoaded.value = true - emit('load', event) + // img.decode() can avoid jank and flash + // see https://www.tunetheweb.com/blog/what-does-the-image-decoding-attribute-actually-do/ + if (img.decode) { + img.decode() + .then(() => { + placeholderLoaded.value = true + emit('load', new Event('load')) + }) + .catch((error) => { + emit('error', error) + }) } - - img.onerror = (event) => { - emit('error', event) + else { + // fallback for browsers that don't support decode() API + img.onload = (event) => { + placeholderLoaded.value = true + emit('load', event) + } + + img.onerror = (event) => { + emit('error', event) + } } markFeatureUsage('nuxt-image') From 41cc2f977affbb8e975923cdfb52b36a33443c1e Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 4 Nov 2025 14:03:44 +0000 Subject: [PATCH 2/2] test: bump bundle size --- test/unit/bundle.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/bundle.test.ts b/test/unit/bundle.test.ts index a45990595..c1fe86f7c 100644 --- a/test/unit/bundle.test.ts +++ b/test/unit/bundle.test.ts @@ -22,7 +22,7 @@ describe.skipIf(process.env.ECOSYSTEM_CI || isWindows)('nuxt image bundle size', }), ]) - expect(roundToKilobytes(withImage.totalBytes - withoutImage.totalBytes)).toMatchInlineSnapshot(`"12.7k"`) + expect(roundToKilobytes(withImage.totalBytes - withoutImage.totalBytes)).toMatchInlineSnapshot(`"12.8k"`) }) })