Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

Early hints emit as=script on rel=modulepreload, producing "preloaded but not used" warnings for every route chunk

オープン 初心者向け
#8,464 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
1/5
見積もり時間
1時間未満
初心者へのやさしさ
90/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
typescript
領域
backend

調査の方向性

@tanstack/start-server-core の early-hints.ts の呼び出し元から始め、そのヒントの構築を @tanstack/router-core の getScriptPreloadAttrs と比較します。iife rel=preload; as=script の動作を維持しつつ、modulepreload のヒントでは as を省略するようにします。modulepreload の Link ヘッダーに as=script が含まれなくなり、既存の CSS および iife のパスが変更されないことが完了条件です。

索引モデルが issue の本文から書いたものです。

説明

information needed
Which project does this relate to?

Router

Describe the bug
Describe the bug

collectStaticHintsFromManifest in @tanstack/start-server-core hardcodes as: "script" on every script hint, regardless of what rel the manifest helper returned.

getScriptPreloadAttrs in @tanstack/router-core correctly returns no as for the module script format — as is only valid alongside rel=preload, which is the iife branch:

// @tanstack/router-core/dist/esm/manifest.js
function getScriptPreloadAttrs(manifest, link, assetCrossOrigin) {
  const preloadLink = resolveManifestAssetLink(link);
  const crossOrigin = getAssetCrossOrigin(assetCrossOrigin, "script") ?? preloadLink.crossOrigin;
  return {
    ...getManifestScriptFormat(manifest) === "iife"
      ? { rel: "preload", as: "script" }
      : { rel: "modulepreload" },          // ← no `as`, correctly
    href: preloadLink.href,
    ...crossOrigin ? { crossOrigin } : {},
  };
}

But the early-hints caller adds it back unconditionally:

// @tanstack/start-server-core/dist/esm/early-hints.js
const attrs = getScriptPreloadAttrs(manifest, link);
const hint = {
  href: attrs.href,
  rel: attrs.rel,     // "modulepreload" for the module format
  as: "script",       // ← always added, even when rel is modulepreload
};

The emitted Link header is therefore:

</assets/index-abc123.js>; rel=modulepreload; as=script

Per the HTML spec, modulepreload does not take an as attribute — the destination is implied ("script"). Browsers register a preload that the module loader never matches, and warn a few seconds after load.

Steps to reproduce
  1. A TanStack Start app with the default module script format and the Link header enabled.
  2. Load any page and open the console.
Expected behaviour

modulepreload hints are emitted without as, matching what getScriptPreloadAttrs already returns. The hint is honoured and no warning is produced.

Actual behaviour

One warning per route chunk, on every page load. On our app that is 14 lines each load:

The resource https://example.com/assets/index-abc123.js was preloaded using link preload
but not used within a few seconds from the window's load event. Please make sure it wasn't
preloaded for nothing.

Observed in Safari 18. No functional impact — but the console becomes unusable for debugging, which is exactly where you look when something actually breaks.

Suggested fix

Carry as through from the helper instead of hardcoding it:

  const attrs = getScriptPreloadAttrs(manifest, link)
  const hint = {
    href: attrs.href,
    rel: attrs.rel,
-   as: 'script',
  }
+ if (attrs.as !== undefined) hint.as = attrs.as

That keeps the iife path (rel=preload; as=script) unchanged and makes the module path spec-correct. The CSS branch below it is already correct — rel=preload; as=style is valid.

Possible origin

#7327 added the Link header, and #7477 later added the iife/module split in getScriptPreloadAttrs. The as: "script" line in early-hints.ts looks like it predates the split and was not revisited when rel stopped always being preload.

Versions
  • @tanstack/start-server-core — reproduced in 1.167.22 (our deployed version, warnings observed in production) and the same code is present in 1.169.37
  • @tanstack/router-core 1.168.17 / 1.171.32
  • @tanstack/react-start 1.167.50
  • @tanstack/react-router 1.168.25
  • Deployed on Cloudflare via Nitro
Workaround

Stripping as=script from modulepreload entries in the Link response header, in our own server entry wrapper. The hint still works — it just becomes valid.

Complete minimal reproducer

see above

Steps to Reproduce the Bug

see above

Expected behavior

see above

Screenshots or Videos

see above

Platform

Not relevant

Additional context

No response

主要言語
TypeScript
スター
15.1k
フォーク
1.9k
平均マージ
2日 35分
マージ済み PR(30日)
136

環境構築

Codespaces で開く

このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

TanStack/router のほかの issue

TanStack/router の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。