Skip to content

Commit 48fb57c

Browse files
committed
bug #72 [Preload] Preload module script entries as modulepreload (Kocal)
This PR was merged into the main branch. Discussion ---------- [Preload] Preload module script entries as modulepreload | Q | A | -------------- | --- | Bug fix? | yes | New feature? | no | Deprecations? | no | Documentation? | no | Issues | - | License | MIT RepriseBundle was preloading entry JavaScript via an HTTP `Link:` header with `rel="preload"; as="script"`, while rendering the entry itself as `<script type="module">`. Classic-script preloads and module scripts use different fetch modes (request credentials, CORS handling), so the browser cannot reuse the preloaded response and discards it, fetching the script a second time. The symptom is a console warning along the lines of "the request credentials mode does not match, consider the crossorigin attribute" or "preloaded ... but not used ... appropriate `as` value". This mismatch was masked until recently: before SRI integrity was added to preload headers in 0.6.1, browsers rejected these preloads on an integrity mismatch before the credentials issue could surface. The fix changes entry module preloads to `rel="modulepreload"`, which matches `<script type="module">` fetch semantics and lets the browser reuse the response correctly. The `integrity` and `crossorigin` attributes are preserved when SRI is enabled. Imported vendor chunks were already using `modulepreload`, so this just makes all module JavaScript consistent. Verified in a browser with SRI on and off: no preload warning in either case, and no regression. Commits ------- 9ea933a [Preload] Preload module script entries as modulepreload
2 parents 2fda3e8 + 9ea933a commit 48fb57c

2 files changed

Lines changed: 7 additions & 3 deletions

File tree

src/Asset/TagRenderer.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ public function renderScriptTags(string $entryName, ?string $packageName = null,
8383
$tagAttributes = ['src' => $url, 'type' => 'module'] + $attributes + $this->scriptAttributes;
8484
$this->applyIntegrity($tagAttributes, $reference, $integrity);
8585
$tags[] = \sprintf('<script %s></script>', $this->attributes($tagAttributes));
86-
$this->preload($url, 'preload', 'script', $reference, $integrity);
86+
// modulepreload, not `preload as=script`: the tag is a module, and a classic-script preload
87+
// mismatches its credentials/CORS mode so the browser discards it.
88+
$this->preload($url, 'modulepreload', null, $reference, $integrity);
8789
}
8890

8991
return implode('', $tags);

tests/Asset/TagRendererTest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,10 @@ public function testRegistersPreloadLinksOnTheRequestWhenWebLinkIsAvailable()
273273
}
274274

275275
$this->assertSame(['modulepreload'], $byHref['/build/shared-e5.js']['rels']);
276-
$this->assertSame(['preload'], $byHref['/build/app-a1b2.js']['rels']);
277-
$this->assertSame('script', $byHref['/build/app-a1b2.js']['as']);
276+
// The <script type=module> entry is preloaded as modulepreload, not `preload as=script` (whose
277+
// classic-script fetch mode mismatches the module and gets discarded by the browser).
278+
$this->assertSame(['modulepreload'], $byHref['/build/app-a1b2.js']['rels']);
279+
$this->assertNull($byHref['/build/app-a1b2.js']['as']);
278280
$this->assertSame(['preload'], $byHref['/build/app-c3.css']['rels']);
279281
$this->assertSame('style', $byHref['/build/app-c3.css']['as']);
280282
}

0 commit comments

Comments
 (0)