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();
|
||||
});
|
||||
|
||||
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 }) => {
|
||||
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"]',
|
||||
match(element) {
|
||||
const htmlElement = element as HTMLImageElement | HTMLIFrameElement;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// Ignore elements using `data:` URI, the `loading` attribute doesn't do anything for these
|
||||
|
|
Loading…
Reference in a new issue