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

Simplified head injection #6034

Merged
merged 4 commits into from
Jan 30, 2023
Merged

Simplified head injection #6034

merged 4 commits into from
Jan 30, 2023

Conversation

matthewp
Copy link
Contributor

@matthewp matthewp commented Jan 30, 2023

Changes

  • This simplifies conditional head injection, fixing a lot of bugs related to CSS being out of place when using multiple levels of layouts with slots.
  • Instead of rendering the head to a string in place, calls to renderHead and maybeRenderHead now instead yield out an instruction. At the page level this instruction is checked and if the head hasn't been rendered it will be.
  • This means that head rendering is handled at the page level. This is the same mechanism used to inject the client directives and that seems to have worked well.
  • Fixes Duplicate css and js bundle tags when mdx is rendered in sub-layout #5715
  • Fixes Duplicate stylesheet injection in production build #5834

Testing

  • Unit tests added for multiple levels of layouts, including layouts that do not include explicit head tags.

Docs

N/A, bug fix

@changeset-bot
Copy link

changeset-bot bot commented Jan 30, 2023

🦋 Changeset detected

Latest commit: 03f66b5

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 the pkg: astro Related to the core `astro` package (scope) label Jan 30, 2023
@@ -13,14 +12,8 @@ const uniqueElements = (item: any, index: number, all: any[]) => {
);
};

async function* renderExtraHead(result: SSRResult, base: string) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removing this function because it causes head rendering to be async. We weren't utilizing this capability anyways. When/if we allow components to inject head content we'll likely want to bring this back, through a small refactor.

}

export const renderHead = createRenderHead;
export function * renderHead(result: SSRResult) {
yield { type: 'head', result } as const;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is a rendering instruction, like what we have for client directives, which tells the page renderer to inject head at the point (if it hasn't already been injected).

@github-actions github-actions bot added the pkg: integration Related to any renderer integration (scope) label Jan 30, 2023
@matthewp matthewp marked this pull request as ready for review January 30, 2023 14:54
@matthewp matthewp requested a review from a team as a code owner January 30, 2023 14:54
@sarah11918 sarah11918 removed the request for review from a team January 30, 2023 14:56
Copy link
Contributor

@bholmesdev bholmesdev left a comment

Choose a reason for hiding this comment

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

Change makes sense to me! All for sticking with existing patterns. Should get ahead of future issues

@matthewp matthewp merged commit 071e1de into main Jan 30, 2023
@matthewp matthewp deleted the css-order-bug branch January 30, 2023 16:55
This was referenced Jan 30, 2023
@robknight
Copy link

There seems to be a bug in the MDX integration test here:

 it('only injects contents into head', async () => {
                        const html = await fixture.readFile('/indexThree/index.html');
                        const { document } = parseHTML(html);

                        const links = document.querySelectorAll('link[rel=stylesheet]');
                        expect(links).to.have.a.lengthOf(1);

                        const scripts = document.querySelectorAll('script[type=module]');
                        expect(scripts).to.have.a.lengthOf(1);
                });

The selector is not scoped to the head tag, so it will match on any link or script tag anywhere in the document.

As per #6057, it seems that this update causes scripts and styles to be inserted into the body, both within MDX documents and components that include layouts, causing a flash of unstyled content. I've also seen this in my own site.

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) pkg: integration Related to any renderer integration (scope)
Projects
None yet
4 participants