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

Merge output: hybrid and output: static #11824

Merged
merged 36 commits into from
Sep 6, 2024
Merged

Merge output: hybrid and output: static #11824

merged 36 commits into from
Sep 6, 2024

Conversation

Princesseuh
Copy link
Member

@Princesseuh Princesseuh commented Aug 23, 2024

Changes

This removes output: 'hybrid' and instead makes static works like hybrid did. If no pages are server-rendered, you still get a normal .html build, like you would with the previous output: 'static', so in theory this is only actually breaking for users of output: 'hybrid'.

To implement this, a new buildOutput property on AstroSettings determine what kind of output should happen, and if it's server you get warned appropriately that an adapter is required for the build to succeed. This property is also used in dev to warn appropriately when using features that require SSR.

The scanning of if a page is pre-rendered or not is now exclusively done during the generation of the route manifest, as opposed to later during the build. This comes with numerous benefits, notably the required ability to know in advance what kind of website we're making before even starting the build, but also the ability to procure more (and accurate) information about the routes earlier anywhere the manifest is used. This could also includes integrations, in the future.

Motivation

The underlying goal of this PR is to promote the usage of SSR sparingly, putting more emphasis on Astro's ability to have only certain pages pre-rendered. We've noticed in our stats and community a great deal of users wrongfully using SSR on every page, slowing down their website unnecessarily.

By having this capacity "unlocked" by default, it also puts greater focus on Astro's ability to build all kinds of websites, not just fully-static ones, which is interesting to explore as Astro grows more and more.

Testing

Tests should pass!

Docs

Oh boy it's a big one for docs! We'll be working on this for the next few weeks and probably more, as this change end up affecting a lot of pages.

Copy link

changeset-bot bot commented Aug 23, 2024

⚠️ No Changeset found

Latest commit: ef10248

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

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

@github-actions github-actions bot added pkg: integration Related to any renderer integration (scope) pkg: astro Related to the core `astro` package (scope) pr: docs A PR that includes documentation for review labels Aug 23, 2024
@github-actions github-actions bot added the pkg: example Related to an example package (scope) label Aug 23, 2024
@github-actions github-actions bot removed the pkg: example Related to an example package (scope) label Aug 23, 2024
.union([z.literal('static'), z.literal('server'), z.literal('hybrid')])
.union([z.literal('static'), z.literal('server')])
Copy link
Member

Choose a reason for hiding this comment

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

This seems weird. A project with output: 'static' can have a non-static output. When I was reading the thread about this on Discord I thought that the merge would remove static and have hybrid as the default.

Copy link
Member Author

Choose a reason for hiding this comment

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

The names here honestly don't matter, since they're not used for logic anymore apart from choosing the default value of prerender

My own take is that the key should be changed to something else than output, Matthew felt like it was too confusing for users if hybrid was the default etc. It's still up for debate!

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I'd prefer to have a boolean prerenderDefault, which defaults to false. No more output.

Copy link
Contributor

Choose a reason for hiding this comment

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

prerenderDefault forces the concept of prerendering onto people who just want to build a regular static (or server) site. People who build mixed sites are the exception.

I don't feel super strongly about hybrid vs static personally. I think it's ok that static has some non-static output because server can already have non-server output too.

export function resolveInjectedRoute(entrypoint: string, root: URL, cwd?: string) {
let resolved;
try {
resolved = require.resolve(entrypoint, { paths: [cwd || fileURLToPath(root)] });
Copy link
Member

Choose a reason for hiding this comment

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

😭 now I can no longer trick Astro into loading a virtual module as an API route.

But it's fine; this gives me an idea of how to circumvent it again.

Copy link
Member Author

Choose a reason for hiding this comment

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

This code is not new, it just moved

Copy link
Member

@alexanderniebuhr alexanderniebuhr left a comment

Choose a reason for hiding this comment

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

We have moved the adapter to https://github.com/withastro/adapters, so this PR can't be merged here anymore.
I would offer to port over the changes to the new repo for you, just let me know if you want me to do that.

Comment on lines -22 to -29
if (config.output !== 'hybrid' && config.output !== 'server') {
throw new AstroError(
'No SSR adapter found.',
'`@astrojs/web-vitals` requires your site to be built with `hybrid` or `server` output.\n' +
'Please add an SSR adapter: https://docs.astro.build/en/guides/server-side-rendering/',
);
}

Copy link
Member Author

Choose a reason for hiding this comment

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

This message doesn't make sense anymore, the route that web-vitals adds will cause the website to be hybrid anyway since it's not pre-rendered.

@delucis
Copy link
Member

delucis commented Aug 31, 2024

there's new buildOutput property on astro:config:done

Hmm, that will be a bit late for Starlight at least – we need to parse user config in astro:config:setup and confirm if it’s OK to inject a route that isn’t prerendered — withastro/starlight#1255 (comment)

And I guess if we inject a route that isn’t prerendered, Astro will switch to “hybrid” so we won’t know it wasn’t hybrid until we made it so.

It’s mainly for error handling in our case, so maybe Astro will give a good enough error anyway? But for stuff like injectRoute() not knowing ahead of time is not ideal.

@Princesseuh
Copy link
Member Author

Yeah, Astro will show an error like "You need an adapter to use server-rendered pages" when you try to build.

I noticed during this work that it makes error handling inside of integrations a bit tougher, as many of the errors end up not making sense anymore.

For what it's worth, even in the previous version there was a way for these errors to fail because a later integration, or the adapter (which always ran last) could change the output mode after you checked, which is no longer possible now

@sarah11918
Copy link
Member

Just noting that docs is (all too) aware of this upcoming change and how it will affect output:* configurations in most Astro projects. This includes streamlining (and updating links) to error messages etc. I believe I am on top of what this means for our regular Astro users who just need to re-understand these build options and how they work.

Where we'll need to be provided explicit documentation is things like e.g. the new buildOutput property on AstroSettings with definition/examples. Anything new introduced, especially as it relates to integration authors, adapters etc. is where you can especially focus your docs efforts.

@@ -161,7 +155,7 @@ export async function staticBuild(
settings.timer.end('Server generate');
return;
}
default:
default: // `settings.buildOutput` will always be one of the above, but TS doesn't know that
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

@Princesseuh Princesseuh Sep 3, 2024

Choose a reason for hiding this comment

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

It's not, the default value is undefined, for the short instant where we don't know yet the output.. but we could make it default to the option of the config I think

@alexanderniebuhr
Copy link
Member

I was going to resolve my blocking commit, because I saw you opened a matching PR in the adapters repo, but I see that the changes in this PR still include a vercel adapter file?

@Princesseuh Princesseuh merged commit 50ca656 into next Sep 6, 2024
13 of 14 checks passed
@Princesseuh Princesseuh deleted the feat/remove-hybrid branch September 6, 2024 23:07
@Princesseuh
Copy link
Member Author

There are still some things here to do, but this PR has been open for way too long and conflicts are getting harder and harder to fix. We'll merge it here and fix the few remaining points in later PRs throughout next week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs pr pkg: astro Related to the core `astro` package (scope) pkg: integration Related to any renderer integration (scope) pr: docs A PR that includes documentation for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants