Skip to content

Commit

Permalink
Prefetch styles only once (#5125)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Co-authored-by: Nate Moore <[email protected]>
Co-authored-by: Nate Moore <[email protected]>
Co-authored-by: My Name <[email protected]>
  • Loading branch information
5 people authored Oct 19, 2022
1 parent fad25ae commit 5a674f9
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/tender-islands-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/prefetch': minor
---

Prefetch CSS files once
10 changes: 9 additions & 1 deletion packages/integrations/prefetch/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from 'astro/config';
import prefetch from '@astrojs/prefetch';

// https://astro.build/config
export default defineConfig({
integrations: [prefetch()],
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "@test/astro-prefetch",
"version": "0.0.0",
"private": true,
"dependencies": {
"@astrojs/prefetch": "workspace:*",
"astro": "workspace:*"
}
}
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -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>
55 changes: 55 additions & 0 deletions packages/integrations/prefetch/test/style-prefetch.test.js
Original file line number Diff line number Diff line change
@@ -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);
});
});
}
});
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5a674f9

Please sign in to comment.