Skip to content

shared script/link referenced by app layout, page layout, and page is emitted (and preloaded) once per occurrence #1760

Description

@jstockdi

What happened?

A <script src> or <link rel="stylesheet"> referenced by more than one of the app layout, page layout, and page is emitted once per occurrence in the built HTML — for the natural pattern "app layout has the shared bundle, page layout and page also reference it", the output contains the same tag three times, plus three modulepreload / preload hints for it.

Consequences beyond bloat:

  • A classic (non-module) duplicate executes repeatedly — double event listeners, double side effects — since only module semantics dedupe by URL in the browser.
  • Duplicated stylesheets apply twice, which can produce cascade-order surprises.
  • Duplicated preload hints waste requests.

There is no warning; the developer only notices when inspecting the output (or debugging a double-fired listener).

Steps to reproduce

  1. Reference the same resource in all three places, e.g.:
<!-- src/layouts/app.html and src/layouts/page.html and src/pages/index.html -->
<script type="module" src="/scripts/shared.js"></script>
<link rel="stylesheet" href="/styles/shared.css" />
  1. greenwood build
  2. Inspect public/index.html.

Observed: 3× the shared <script> tag, 3× the shared stylesheet <link>, 3× modulepreload, 3× preload. Expected: each once.

Environment

  • Greenwood v0.34.0 (reproduced on current master)
  • NodeJS v22.20
  • Linux

Additional Context

Two compounding spots:

  1. packages/cli/src/lib/layout-utils.jsmergeContentIntoLayout builds mergedLinks (line 143) and mergedScripts (line 186) by concatenating parent + child head tags with no dedupe by src/href, so each layout-merge pass preserves duplicates.
  2. packages/cli/src/lib/resource-utils.js:214matchingRoute.resources is built with resources.map(...), preserving duplicates (only the compilation.resources Map is deduped), and the standard HTML plugin injects one preload hint per occurrence while rewriting each tag.

Happy to submit a PR: dedupe merged <script src>/<link href> tags in the layout merge (keeping the first occurrence, so app layout → page layout → page order is preserved), plus a Set on matchingRoute.resources, with regression assertions folded into the existing build.default.workspace-layouts-page-and-app test case.

(Found during the same audit pass as #1707/#1709/#1711 etc.)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions