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:
parent
fad25aef2f
commit
5a674f976d
9 changed files with 141 additions and 1 deletions
5
.changeset/tender-islands-watch.md
Normal file
5
.changeset/tender-islands-watch.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/prefetch': minor
|
||||
---
|
||||
|
||||
Prefetch CSS files once
|
|
@ -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 {}
|
||||
}
|
||||
|
||||
|
|
7
packages/integrations/prefetch/test/fixtures/style-prefetch/astro.config.mjs
vendored
Normal file
7
packages/integrations/prefetch/test/fixtures/style-prefetch/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import prefetch from '@astrojs/prefetch';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [prefetch()],
|
||||
});
|
9
packages/integrations/prefetch/test/fixtures/style-prefetch/package.json
vendored
Normal file
9
packages/integrations/prefetch/test/fixtures/style-prefetch/package.json
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "@test/astro-prefetch",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@astrojs/prefetch": "workspace:*",
|
||||
"astro": "workspace:*"
|
||||
}
|
||||
}
|
18
packages/integrations/prefetch/test/fixtures/style-prefetch/src/pages/index.astro
vendored
Normal file
18
packages/integrations/prefetch/test/fixtures/style-prefetch/src/pages/index.astro
vendored
Normal 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>
|
15
packages/integrations/prefetch/test/fixtures/style-prefetch/src/pages/style1.astro
vendored
Normal file
15
packages/integrations/prefetch/test/fixtures/style-prefetch/src/pages/style1.astro
vendored
Normal 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>
|
15
packages/integrations/prefetch/test/fixtures/style-prefetch/src/pages/style2.astro
vendored
Normal file
15
packages/integrations/prefetch/test/fixtures/style-prefetch/src/pages/style2.astro
vendored
Normal 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>
|
55
packages/integrations/prefetch/test/style-prefetch.test.js
Normal file
55
packages/integrations/prefetch/test/style-prefetch.test.js
Normal 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);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
|
@ -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'
|
||||
|
|
Loading…
Reference in a new issue