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

Finalize <head>, <body>, <html> #26

Merged
merged 13 commits into from
Dec 9, 2021
Merged

Finalize <head>, <body>, <html> #26

merged 13 commits into from
Dec 9, 2021

Conversation

FredKSchott
Copy link
Member

@FredKSchott FredKSchott commented Dec 1, 2021

  • Start Date: 2021-11-30
  • Status: Accepted

Summary

Finalize behavior around <head>, <body>, <html>, and <!DOCTYPE html> elements in Astro component templates.

Links

@FredKSchott FredKSchott changed the title Create 0000-finalize-head-body.md Finalize <head>, <body>, <html> Dec 1, 2021
@FredKSchott FredKSchott self-assigned this Dec 1, 2021
- an `<html>` tag is always included in the final output
- `<!DOCTYPE html>`
- completely ignored in a component template
- a `<!DOCTYPE html>` tag is always included in the final output
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm fine with this personally, we should search discord just to be sure there aren't people out there wanting to use older doctypes though.

@matthewp
Copy link
Contributor

matthewp commented Dec 1, 2021

Couple of notes:

  1. This is missing use-cases. There are some known use-case from within SPA frameworks, but are those use-cases relevant in a framework where you have control over the entire page template? A comparison of the approaches would be helpful here.
  2. One drawback that is not listed here is streaming SSR. This probably prevents it. If we have to wait for all components to render before knowing what to put into the head, we can't stream out the HTML.
    • This is perhaps not true if there was a static requirement place on the component-level head usage (in which case it could be extracted at compile time), but this RFC doesn't talk about any restrictions.

Copy link
Contributor

@jonathantneal jonathantneal left a comment

Choose a reason for hiding this comment

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

I can dig it. Left some comments.

@FredKSchott
Copy link
Member Author

@matthewp: This is missing use-cases. There are some known use-case from within SPA frameworks, but are those use-cases relevant in a framework where you have control over the entire page template? A comparison of the approaches would be helpful here.

Let me see if I can improve the "motivation" section based on your other item of feedback. This section is meant to answer this question.

@matthewp: One drawback that is not listed here is streaming SSR. This probably prevents it. If we have to wait for all components to render before knowing what to put into the head, we can't stream out the HTML.

I believe that this is already not supported based on how layouts work, but I agree that this is making that lack of support explicit. I'll add a note to the Drawbacks section.

@FredKSchott
Copy link
Member Author

FredKSchott commented Dec 2, 2021

@matthewp @jonathantneal thank you for the feedback and comments on this RFC, and @natemoo-re for giving feedback in person.

Based on feedback (and a better understanding of how this all works in the current codebase) I took another pass at this and really re-scoped the RFC:

  • <head> injection/collapsing has been removed as out-of-scope, to be tackled in a separate RFC.
  • No longer talking about adding or removing head/body/html elements on the page automatically, and instead deferring to the component author.

The RFC is now only focused on simplifying things in the codebase and committing to a more straightforward render behavior. Hopefully the smaller scope makes this easier to review. PTAL when you can!

Note: previous RFC draft still available here

- `<html>`, `<body>`, `<head>`
- compiler: will be left as-is in the component template.
- runtime: will be left as-is in final page HTML output.
- runtime: may warn if duplicate `html`, `body`, and `head` tags are included in final page HTML output.
Copy link
Contributor

Choose a reason for hiding this comment

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

this may be difficult, remembering that the runtime only see strings of HTML, so not easy to detect multiple tags.

Copy link
Member Author

Choose a reason for hiding this comment

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

I can it make more clear that this isn't required, and is just a suggestion of something that is not impossible/blocked by this RFC.


## Compiler Changes

- `src/pages` and `src/layouts` will no longer be parsed or rendered differently from other components
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 agree on this

Copy link
Contributor

@jonathantneal jonathantneal left a comment

Choose a reason for hiding this comment

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

I have one lingering concern left. Looking for clarity regarding <!doctype html>.

@FredKSchott
Copy link
Member Author

Resolved in convo above!

@RafidMuhymin
Copy link
Member

RafidMuhymin commented Dec 7, 2021

I am mentioning a use case for hoisting <link> or <meta> tags to the <head> of the page.

Most of the images on a webpage should be lazily loaded. But some images like banners, hero images, or logos (it should be inline though) should be eagerly loaded. To do this, one should not only tell the browser to eagerly load the image using loading="eager" but he should also preload the image. For this, users can pass a format using the preload prop to the <Image> component to eagerly preload the image.

But when I was implementing this feature I found that unlike v0.20, <link>, <meta> or other tags that should be in the <head> of the page aren't hoisted.

So, not only the <Image> component is affected but any third-party package or even a user wants to implement a similar feature can't do this.


- runtime: will remove current post-build head injection, which involves a fragile `'</head>'` string find-and-replace.
- compiler: will add a new `head: string` (or: `injectHead(): string`) property to the compiler transform options, which will inject the given HTML string into the bottom of a `<head>` element, if one is return by the compiler.
- runtime: will provide this value head injection value to the compiler, and throw an exception if not used/called exactly once during a page render.
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

## Head Injection Changes

- runtime: will remove current post-build head injection, which involves a fragile `'</head>'` string find-and-replace.
- compiler: will add a new `head: string` (or: `injectHead(): string`) property to the compiler transform options, which will inject the given HTML string into the bottom of a `<head>` element, if one is return by the compiler.
Copy link
Contributor

@matthewp matthewp Dec 7, 2021

Choose a reason for hiding this comment

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

I like injectHead() rather than injectStyles() / injectLinks() because it gives the runtime the freedom to inject anything it needs into the bottom of the head, in whatever order it decides is best.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this should be part of the compiler options though. I would expect this to be part of the runtime code. Either part of the $$result object or an import, but I think this is an implementation detail that doesn't need to be spelled out in the RFC.

Copy link
Member Author

Choose a reason for hiding this comment

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

ah, I thought that we needed it to be in the compiler since transform() returns a final string, but maybe I misunderstood. Agreed, happy to finalize this in the implementation since this RFC is mainly focused on expected behavior.

@FredKSchott
Copy link
Member Author

RFC Notes:

  • document this behavior in the docs site and tests
  • Question: can we only add a <!DOCTYPE html> if an <html> element is detected?
    • we need a head already, so "html fragment" is not currently a supported usecase by this RFC
  • Status: Accepted with consensus on RFC call

@FredKSchott FredKSchott merged commit 7451484 into main Dec 9, 2021
@matthewp matthewp deleted the FredKSchott-patch-2 branch December 9, 2021 16:46
@matthewp
Copy link
Contributor

@RafidMuhymin Thank you, this is great feedback and something we should figure out a way to support. If you'd like, we can start a new Discussion in this repo to talk about that use-case more.

@RafidMuhymin
Copy link
Member

@matthewp Yeah, I have no problem doing that if you tell me what's the way of starting a discussion in this repo

@FredKSchott
Copy link
Member Author

yes please! Happy to revisit that part of this, it came up in the convo and the balance we need to strike is supporting users who are building pages and forgot to add the doctype (and may not even know what that tag means).

@gabrielgrant
Copy link

gabrielgrant commented Jan 2, 2022

@FredKSchott To confirm/clarify from the comments buried in the review and your notes from the RFC call -- am I understanding correctly that the decision was to auto-add doctype only in the case that an <html> element is detected?

That seems like a sensible compromise to both seamlessly avoid problems when uses forget to add doctype themselves, while still allowing for generating non-full-HTML-page content such as JSON data or @jacobrask 's use case of page fragments, an RSS feed, or dynamic SVG

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants