Prefetch styles only once (#5125)

* test1

* fixed test

* removed console.log

* changeset

* pnpm-lock

* fixed test again

* fta

* fta2

* fix: wait for fetch

* -fixed test template

* empty

Co-authored-by: Matthew Phillips <matthew@skypack.dev>
Co-authored-by: Nate Moore <nate@astro.build>
Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
Co-authored-by: My Name <my.name@my-company.com>
This commit is contained in:
Jelenkee 2022-10-19 21:20:45 +02:00 committed by GitHub
parent fad25aef2f
commit 5a674f976d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 141 additions and 1 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/prefetch': minor
---
Prefetch CSS files once

View file

@ -5,6 +5,7 @@ import requestIdleCallback from './requestIdleCallback.js';
const events = ['mouseenter', 'touchstart', 'focus'];
const preloaded = new Set<string>();
const loadedStyles = new Set<string>();
function shouldPreload({ href }: { href: string }) {
try {
@ -53,7 +54,14 @@ async function preloadHref(link: HTMLAnchorElement) {
const html = parser.parseFromString(contents, 'text/html');
const styles = Array.from(html.querySelectorAll<HTMLLinkElement>('link[rel="stylesheet"]'));
await Promise.all(styles.map((el) => fetch(el.href)));
await Promise.all(
styles
.filter((el) => !loadedStyles.has(el.href))
.map((el) => {
loadedStyles.add(el.href);
return fetch(el.href);
})
);
} catch {}
}

View file

@ -0,0 +1,7 @@
import { defineConfig } from 'astro/config';
import prefetch from '@astrojs/prefetch';
// https://astro.build/config
export default defineConfig({
integrations: [prefetch()],
});

View file

@ -0,0 +1,9 @@
{
"name": "@test/astro-prefetch",
"version": "0.0.0",
"private": true,
"dependencies": {
"@astrojs/prefetch": "workspace:*",
"astro": "workspace:*"
}
}

View file

@ -0,0 +1,18 @@
---
---
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home</title>
</head>
<body>
<h1>Home</h1>
<ul>
<li><a href="/style1" rel="prefetch">1</a></li>
<li><a href="/style2" rel="prefetch">2</a></li>
</ul>
</body>
</html>

View file

@ -0,0 +1,15 @@
---
---
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Style1</title>
<link rel="stylesheet" href="/main.css">
</head>
<body>
<h1>Style1</h1>
</body>
</html>

View file

@ -0,0 +1,15 @@
---
---
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Style2</title>
<link rel="stylesheet" href="/main.css">
</head>
<body>
<h1>Style2</h1>
</body>
</html>

View file

@ -0,0 +1,55 @@
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = testFactory({ root: './fixtures/style-prefetch/' });
test.describe('Style prefetch', () => {
test.describe('dev', () => {
let devServer;
test.beforeEach(async ({ astro }) => {
devServer = await astro.startDevServer();
});
test.afterEach(async () => {
await devServer.stop();
});
testPrefetch();
});
test.describe('build', () => {
let previewServer;
test.beforeAll(async ({ astro }) => {
await astro.build();
previewServer = await astro.preview();
});
// important: close preview server (free up port and connection)
test.afterAll(async () => {
await previewServer.stop();
});
testPrefetch();
});
function testPrefetch() {
test.describe('prefetches rel="prefetch" links', () => {
test('style fetching', async ({ page, astro }) => {
const requests = [];
page.on('request', async (request) => requests.push(request.url()));
await page.goto(astro.resolveUrl('/'));
await page.waitForLoadState('networkidle');
await expect(requests.filter(req => req.includes('/style1'))).toBeTruthy();
await expect(requests.filter(req => req.includes('/style2'))).toBeTruthy();
const cssRequestCount = requests.filter(req => req.includes('/main.css')).length;
await expect(cssRequestCount).toBe(1);
});
});
}
});

View file

@ -3011,6 +3011,14 @@ importers:
'@astrojs/prefetch': link:../../..
astro: link:../../../../../astro
packages/integrations/prefetch/test/fixtures/style-prefetch:
specifiers:
'@astrojs/prefetch': workspace:*
astro: workspace:*
dependencies:
'@astrojs/prefetch': link:../../..
astro: link:../../../../../astro
packages/integrations/react:
specifiers:
'@babel/core': '>=7.0.0-0 <8.0.0'