Skip to content

Using scripts inside a template prevents inlining when used in other locations  #13795

@san4d

Description

@san4d

Astro Info

> astro info

Astro                    v5.7.10
Node                     v20.19.0
System                   macOS (arm64)
Package Manager          pnpm
Output                   server
Adapter                  astro-sst
Integrations             astro-icon
                         htmx
                         posthogJs
                         @astrojs/partytown

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

Chrome, Brave, likely all

Describe the Bug

Problem

Consider an Astro component with both HTML and a script tag:

<!-- TestItem.astro -->
<h2> I'm a test </h2>
<script>
    console.log('Running a script in TestItem')
</script>

Suppose you want to include that component and that you are already using that component in the same page:

<template>
    <TestItem/>
</template>
<TestItem/>

What you'll find is the script in TestItem never runs. In fact, the script is not inlined.

Context

I ran into this when using web components in a list. Since the list can have any/all of its items deleted, I wanted to have a template available for creating new items. Because of this issue my web component never registers, meaning items outside the template have no interactivity.

Workaround

If you move the template definition after the component usage, the script runs. For my web component usecase, this is enough to unblock me:

<TestItem/>
<template>
    <TestItem/>
</template>

Analysis

My guess is Astro is treating the script in the template and the script outside of the template as the same and therefore only runs it once. Since the first occurrence is happening inside the template, it has no effect. Here's a direct example:

<template>
	<script>
		console.log('Logging inside a template does not')
	</script>
</template>
<script>
	console.log('Logging outside a template works')
</script>

Note that the script inside the template does run on insert:

<template id="simple-script">
    <script>
        console.log('Script inside template runs after insert')
    </script>
</template>
<script>
    const templ = document.getElementById('simple-script').content.cloneNode(true)
    document.body.append(templ)
</script>

What's the expected result?

I would not expect scripts inside the template to prevent scripts outside the template from running. I also would expect the scripts in the template to run on insert.

In my example, I would expect to see one log from TestItem when it's used bot inside and outside of a template.

Link to Minimal Reproducible Example

https://stackblitz.com/edit/github-jfjh51f5?file=src%2Fpages%2Findex.astro

Participation

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    - P3: minor bugAn edge case that only affects very specific usage (priority)

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions