Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add experimental client prerender #9644

Merged

Conversation

rossrobino
Copy link
Contributor

@rossrobino rossrobino commented Jan 8, 2024

Changes

Discussed in withastro/roadmap#794

This adds an experimental progressive enhancement to enable the use of the Speculation Rules API to prerender pages (including running client-side JS) on the client. This feature is currently supported in Chrome and Edge without a flag. A feature that uniquely benefits multi-page application navigations.

I have limited experience with tree-shaking, but in my testing, it appears to be working if the feature is not enabled.

Testing

You can use the minimal example to test this feature with these modifications:

astro.config.mjs

import { defineConfig } from 'astro/config';

// https://astro.build/config
export default defineConfig({
+    prefetch: true,
+    experimental: {
+        clientPrerender: true,
+    },
});

index.astro

---

---

<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
		<title>Astro</title>
	</head>
	<body>
		<h1>Astro</h1>
+.             <a href="/test" data-astro-prefetch>Prerender Test</a>
	</body>
</html>

Add new page: test.astro

---

---

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
        <meta name="viewport" content="width=device-width" />
        <meta name="generator" content={Astro.generator} />
        <title>Astro</title>
        <script>
            const layoutShift = () => {
                const h2 = document.querySelector("h2");
                h2.textContent = "Layout Shift"
            }

            layoutShift();

            const prerenderContent = () => {
                let text: string;
    
                //@ts-expect-error - `document.prerendering` is not supported in all browsers
                if (document.prerendering) {
                    text = "Prerendered on the client.";
                } else {
                    text = "Not prerendered.";
                }
                
                const preredered = document.createElement("p");
                preredered.textContent = text;
                document.body.appendChild(preredered);
            }

            prerenderContent();

        </script>
    </head>
    <body>
        <h1>Experimental Client Prerender</h1>
        <h2></h2>
        <p>The paragraph below and the h2 above are rendered by client side JavaScript. You can see the difference by navigating to this page from another, in comparison to refreshing the page.</p>
    </body>
</html>

Docs

/cc @withastro/maintainers-docs for feedback!

I have added jsdoc comments to my type, I'm not sure if any other docs will be needed since it is experimental.

Copy link

changeset-bot bot commented Jan 8, 2024

🦋 Changeset detected

Latest commit: d2ddd47

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions bot added pkg: astro Related to the core `astro` package (scope) pr: docs A PR that includes documentation for review labels Jan 8, 2024
Copy link
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code-wise, this looks good to me.

We need:

@ematipico ematipico added this to the 4.2.0 milestone Jan 12, 2024
Copy link
Member

@sarah11918 sarah11918 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for submitting this, @rossrobino ! I'm sure people will be excited to try this feature!

As Ema requested, a changeset is necessary here and the content should be of the form:

Adds an experimental feature flag clientPrerender to allow ...

I also made a suggestion to revise the docs so that they more matched the existing pattern/style. Please do make any factual corrections, and/or let me know if the nuance isn't quite right!

ALSO: I do suspect additional usage documentation might be necessary. For example, our existing Prefetch has several options, such as a default strategy and ways to opt-out on individual pages. I'll review your usage examples in the PR description more closely to decide what else might be needed. At the very least, there should be mention of whether this applies globally by default once enabled, how or whether one can opt out (or in) on an individual page/link basis etc.

So, I'll be back!

And... I'm back.

Here are my questions so far that I think people will have that should be answered in documentation:

  • why/when would someone choose to enable this flag? What does this change or unlock?

  • once the flag is enabled, what default behaviour changes (without doing anything else) if any? In other words, what is now different that people might need to check in their deployed project?

  • Is this a global, default change or does this provide a new opt-in, per link/page feature? If it's global, is it possible to opt out on a per link/page basis, and if so, how?

  • how does this relate to our existing Prefetch feature and its options? Does it have its own config options or strategies involved? (tap, hover, etc.) Does it inherit these values from the main prefetch config?

packages/astro/src/@types/astro.ts Show resolved Hide resolved
packages/astro/src/@types/astro.ts Outdated Show resolved Hide resolved
@sarah11918
Copy link
Member

Thanks so much, @rossrobino ! Great additions to the docs! I'll just do a little light editing of it, but I feel like we're providing much more helpful guidance and context for those who want to experiment with this feature!

@rossrobino
Copy link
Contributor Author

Code-wise, this looks good to me.

We need:

@ematipico

I've added a changeset and tests, let me know if anything else is needed. Thanks!

Copy link
Member

@sarah11918 sarah11918 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, thanks again @rossrobino ! I had a chance to go through and make some suggestions for changeset/config docs.

Please review these and see what you think. Do feel free to make any changes if something is not right! This would be my suggested format based on how I think things are working, but if we need to correct, go ahead and do so!

.changeset/sixty-dogs-sneeze.md Outdated Show resolved Hide resolved
packages/astro/src/@types/astro.ts Outdated Show resolved Hide resolved
@rossrobino
Copy link
Contributor Author

@sarah11918 thank you for editing! I added them with a few modifications, let me know what you think.

Copy link
Member

@ematipico ematipico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! @bluwy, could you give your review too, please?

@ematipico ematipico requested a review from bluwy January 15, 2024 14:54
Copy link
Member

@bluwy bluwy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small nits below, but great work on the tests and implementation! Sorry for the long wait for the review, been stuck with other stuff.

packages/astro/src/@types/astro.ts Outdated Show resolved Hide resolved
packages/astro/src/prefetch/index.ts Outdated Show resolved Hide resolved
Comment on lines +221 to +227
if (
clientPrerender &&
HTMLScriptElement.supports &&
HTMLScriptElement.supports('speculationrules')
) {
// this code is tree-shaken if unused
appendSpeculationRules(url);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe in the future we can use prerender/prefetch when using with: 'link' or with: 'fetch' respectively. That way links that enter the viewport don't get prerendered entirely. But we can improve this later if needed.

Copy link
Member

@sarah11918 sarah11918 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, things are looking good! I think I'm only correcting commas and hyphens here. 😄

So, making this official call right now: no hyphens on any "pre" words! So, please be sure we've consistently got prefetch and prerender everywhere.

.changeset/sixty-dogs-sneeze.md Outdated Show resolved Hide resolved
packages/astro/src/@types/astro.ts Outdated Show resolved Hide resolved
.changeset/sixty-dogs-sneeze.md Outdated Show resolved Hide resolved
.changeset/sixty-dogs-sneeze.md Outdated Show resolved Hide resolved
packages/astro/src/@types/astro.ts Outdated Show resolved Hide resolved
Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com>
rossrobino and others added 6 commits January 15, 2024 10:45
Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com>
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
Copy link
Member

@sarah11918 sarah11918 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm really happy with where these docs ended up! Thank you for your help @rossrobino ! 🥳

@rossrobino
Copy link
Contributor Author

@sarah11918 great, thanks for all of your help!

@ematipico ematipico merged commit a5f1682 into withastro:main Jan 17, 2024
13 of 14 checks passed
@astrobot-houston astrobot-houston mentioned this pull request Jan 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pkg: astro Related to the core `astro` package (scope) pr: docs A PR that includes documentation for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants