Skip to content

<script> location regression in Astro 5.16.9 #15627

@delucis

Description

@delucis

Astro Info

Astro                    v5.17.3
Vite                     v6.4.1
Node                     v20.19.1
System                   Linux (x64)
Package Manager          npm
Output                   static
Adapter                  none
Integrations             none

If this issue only occurs in one browser, which browser is a problem?

n/a

Describe the Bug

Prior to Astro 5.16.9, a <script> in a component would be rendered adjacent to that component.

For example, the following component:

<p>Example</p>
<script>console.log('hello')</script>

would be rendered to something like:

<p>Example</p>
<script type="module" src="/some/path/to/the/built/script.js"></script>

In basic cases, this is still the case but #15147 changed logic when rendering happens via a slot.

For example, if the component above is passed as a child to this component:

---
const html = await Astro.slots.render('default');
---

<p>Parent example</p>
<Fragment set:html={html} />

Then the output is something like:

<p>Parent example</p>
<script type="module" src="/some/path/to/the/built/script.js"></script>
<p>Example</p>

Note how the <script> moved in front of the <p>Example</p>.

More extreme cases can see the script moved up the HTML tree entirely for example the following input in the minimal reproduction where ComponentB contains a script and ComponentA uses the Astro.slots.render() pattern:

<ComponentA>
	<ol>
		<li>Some text</li>
		<li><ComponentB /></li>
	</ol>
</ComponentA>

In this case, the script from ComponentB gets rendered before the opening <ol> tag.

This can cause issues for things like CSS where :first-child and other child and sibling selectors may not expect a script from a child component to appear. In withastro/starlight#3712 it broke Starlight components due to expectations about the HTML output Astro would produce.

It’s also harder to work with this behaviour because it’s unpredictable: where the <script> is rendered depends on how the component is rendered.

What's the expected result?

I would expect the <script> to be rendered in a consistent location. Ideally it should not be rendered “outside” of its own tree because doing so forces users to design parent components to handle the “risk” that a child might contain a <script> that could show up in an unexpected location. That kind of “defensive” pattern is a DX smell.

Link to Minimal Reproducible Example

https://stackblitz.com/edit/github-gnfhebf7

Participation

  • I am willing to submit a pull request for this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    - P4: importantViolate documented behavior or significantly impacts performance (priority)pkg: astroRelated to the core `astro` package (scope)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions