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') 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"`) }) })