mirror of
https://github.com/withastro/astro.git
synced 2025-01-22 10:31:53 -05:00
* fix: audit incorrectly flag images as above the fold (#12993) * chore: add changeset * Add additional tests for perf audit
This commit is contained in:
parent
22eafffd10
commit
9ce0038021
6 changed files with 123 additions and 2 deletions
5
.changeset/cuddly-rings-sing.md
Normal file
5
.changeset/cuddly-rings-sing.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes the issue that audit incorrectly flag images as above the fold when the scrolling container is not body
|
|
@ -44,6 +44,55 @@ test.describe('Dev Toolbar - Audits', () => {
|
||||||
await appButton.click();
|
await appButton.click();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('does not warn about perf issue for below the fold image after mutation when body is unscrollable', async ({ page, astro }) => {
|
||||||
|
await page.goto(astro.resolveUrl('/audits-perf-body-unscrollable'));
|
||||||
|
|
||||||
|
const toolbar = page.locator('astro-dev-toolbar');
|
||||||
|
const appButton = toolbar.locator('button[data-app-id="astro:audit"]');
|
||||||
|
await appButton.click();
|
||||||
|
|
||||||
|
const auditCanvas = toolbar.locator('astro-dev-toolbar-app-canvas[data-app-id="astro:audit"]');
|
||||||
|
const auditHighlights = auditCanvas.locator('astro-dev-toolbar-highlight');
|
||||||
|
|
||||||
|
expect(auditHighlights).toHaveCount(1);
|
||||||
|
|
||||||
|
await page.click('body');
|
||||||
|
|
||||||
|
let consolePromise = page.waitForEvent('console');
|
||||||
|
await page.locator('#mutation-button').click();
|
||||||
|
await consolePromise;
|
||||||
|
|
||||||
|
await appButton.click();
|
||||||
|
|
||||||
|
expect(auditHighlights).toHaveCount(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('does not warn about perf issue for below the fold image in relative container', async ({ page, astro }) => {
|
||||||
|
await page.goto(astro.resolveUrl('/audits-perf-relative'));
|
||||||
|
|
||||||
|
const toolbar = page.locator('astro-dev-toolbar');
|
||||||
|
const appButton = toolbar.locator('button[data-app-id="astro:audit"]');
|
||||||
|
await appButton.click();
|
||||||
|
|
||||||
|
const auditCanvas = toolbar.locator('astro-dev-toolbar-app-canvas[data-app-id="astro:audit"]');
|
||||||
|
const auditHighlights = auditCanvas.locator('astro-dev-toolbar-highlight');
|
||||||
|
|
||||||
|
expect(auditHighlights).toHaveCount(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('can warn about perf issue for below the fold image in absolute container', async ({ page, astro }) => {
|
||||||
|
await page.goto(astro.resolveUrl('/audits-perf-absolute'));
|
||||||
|
|
||||||
|
const toolbar = page.locator('astro-dev-toolbar');
|
||||||
|
const appButton = toolbar.locator('button[data-app-id="astro:audit"]');
|
||||||
|
await appButton.click();
|
||||||
|
|
||||||
|
const auditCanvas = toolbar.locator('astro-dev-toolbar-app-canvas[data-app-id="astro:audit"]');
|
||||||
|
const auditHighlights = auditCanvas.locator('astro-dev-toolbar-highlight');
|
||||||
|
|
||||||
|
expect(auditHighlights).toHaveCount(1);
|
||||||
|
});
|
||||||
|
|
||||||
test('can handle mutations', async ({ page, astro }) => {
|
test('can handle mutations', async ({ page, astro }) => {
|
||||||
await page.goto(astro.resolveUrl('/audits-mutations'));
|
await page.goto(astro.resolveUrl('/audits-mutations'));
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
import { Image } from "astro:assets";
|
||||||
|
import walrus from "../light_walrus.avif";
|
||||||
|
---
|
||||||
|
<div style="height: 9000px;"></div>
|
||||||
|
<div style="position:absolute;top:0;left:0">
|
||||||
|
<Image src={walrus} loading="lazy" alt="A walrus" />
|
||||||
|
</div>
|
||||||
|
<div style="height: 9000px;"></div>
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
import { Image } from "astro:assets";
|
||||||
|
import walrus from "../light_walrus.avif";
|
||||||
|
---
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="scroll-container">
|
||||||
|
<Image src={walrus} loading="lazy" alt="A walrus" />
|
||||||
|
<div style="height: 9000px;"></div>
|
||||||
|
|
||||||
|
<Image src={walrus} loading="lazy" alt="A walrus" />
|
||||||
|
<button id="mutation-button">Mutation</button>
|
||||||
|
<div style="height: 9000px;"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100dvh;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
#scroll-container {
|
||||||
|
height: 100dvh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const mutationButton = document.getElementById('mutation-button');
|
||||||
|
mutationButton?.addEventListener('click', () => {
|
||||||
|
const dummyElement = document.createElement('div');
|
||||||
|
document.body.appendChild(dummyElement);
|
||||||
|
|
||||||
|
console.log('mutation');
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
import { Image } from "astro:assets";
|
||||||
|
import walrus from "../light_walrus.avif";
|
||||||
|
---
|
||||||
|
|
||||||
|
<div style="height: 9000px;"></div>
|
||||||
|
<div style="position:relative">
|
||||||
|
<Image src={walrus} loading="lazy" alt="A walrus" />
|
||||||
|
</div>
|
|
@ -35,8 +35,14 @@ export const perf: AuditRuleWithSelector[] = [
|
||||||
'img:not([loading]), img[loading="eager"], iframe:not([loading]), iframe[loading="eager"]',
|
'img:not([loading]), img[loading="eager"], iframe:not([loading]), iframe[loading="eager"]',
|
||||||
match(element) {
|
match(element) {
|
||||||
const htmlElement = element as HTMLImageElement | HTMLIFrameElement;
|
const htmlElement = element as HTMLImageElement | HTMLIFrameElement;
|
||||||
|
|
||||||
// Ignore elements that are above the fold, they should be loaded eagerly
|
// Ignore elements that are above the fold, they should be loaded eagerly
|
||||||
const elementYPosition = htmlElement.getBoundingClientRect().y + window.scrollY;
|
let currentElement = element as HTMLElement;
|
||||||
|
let elementYPosition = 0;
|
||||||
|
while (currentElement) {
|
||||||
|
elementYPosition += currentElement.offsetTop;
|
||||||
|
currentElement = currentElement.offsetParent as HTMLElement;
|
||||||
|
}
|
||||||
if (elementYPosition < window.innerHeight) return false;
|
if (elementYPosition < window.innerHeight) return false;
|
||||||
|
|
||||||
// Ignore elements using `data:` URI, the `loading` attribute doesn't do anything for these
|
// Ignore elements using `data:` URI, the `loading` attribute doesn't do anything for these
|
||||||
|
@ -55,7 +61,12 @@ export const perf: AuditRuleWithSelector[] = [
|
||||||
const htmlElement = element as HTMLImageElement | HTMLIFrameElement;
|
const htmlElement = element as HTMLImageElement | HTMLIFrameElement;
|
||||||
|
|
||||||
// Ignore elements that are below the fold, they should be loaded lazily
|
// Ignore elements that are below the fold, they should be loaded lazily
|
||||||
const elementYPosition = htmlElement.getBoundingClientRect().y + window.scrollY;
|
let currentElement = element as HTMLElement;
|
||||||
|
let elementYPosition = 0;
|
||||||
|
while (currentElement) {
|
||||||
|
elementYPosition += currentElement.offsetTop;
|
||||||
|
currentElement = currentElement.offsetParent as HTMLElement;
|
||||||
|
}
|
||||||
if (elementYPosition > window.innerHeight) return false;
|
if (elementYPosition > window.innerHeight) return false;
|
||||||
|
|
||||||
// Ignore elements using `data:` URI, the `loading` attribute doesn't do anything for these
|
// Ignore elements using `data:` URI, the `loading` attribute doesn't do anything for these
|
||||||
|
|
Loading…
Reference in a new issue