Link
前言
在現代前端框架盛行的年代,很少會需要大量的手動設置 <link>,基本上 bundler 會處理好各種 JavaScript, CSS 的載入,只有少部分會需要在 index.html 設定;也因此顯少有機會深入研究 <link> 的各種 attribute。
為何會在 HTTP 的系列文章提到 <link> 呢?因為 HTTP Response Header 也可以設定 Link!所以就趁這篇文章,也順便把 HTML 的 <link> 也介紹一遍吧~
Browser compatibility of HTTP Response Header Link
翻開 MDN 文件 的話,會發現其實各瀏覽器大約都在 2022 ~ 2023 年才開始支援在 HTTP Response Header 設定 <Link>,其實算是蠻新的功能。我自己也只有在 hackerone 看到有設定

Basic Syntax of HTTP Link
以上圖 hackerone 的網站為例
</assets/static/main_css-ClkKLtaZ.css>; rel=preload; as=style; nopush
前面三個區塊,我想應該沒什麼問題,等同於
<link href="/assets/static/main_css-ClkKLtaZ.css" rel="preload" as="style" />
至於 nopush 是什麼呢?恩...這會牽扯到 HTTP/2 的 Server Push
Why use HTTP Link instead of HTML <link>?
簡單講,就是因為 HTTP Link 可以比較快載入。承接我去年寫過的
假設某網站的首頁回傳的 HTTP Response 為
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Date: Tue, 18 Nov 2025 11:09:52 GMT
Transfer-Encoding: chunked
Link: </assets/static/main_css-ClkKLtaZ.css>; rel=preload; as=style
a
<html><head>
Backend 還在 Query DB,生成這一頁的資料...
瀏覽器收到 Response Headers 的當下,就可以開始 preload 對應的資源,不用等 HTML 回傳!
P.S. 在 HTTP/1.1 的世界,如果想要先回傳 Headers,但又不確定 Content-Length 是多少的話,可以用 Transfer-Encoding: chunked 達到分塊傳輸
HTML <link> 前言
現在我們知道 HTTP Response Header 設定的 Link 跟 HTML <link> 在速度上的差異了
接下來,我們來看看 HTML <link> 有哪些 attributes
<link rel>
rel = relationship
接下來會介紹幾個比較常用的值
瀏覽器載入資源的 Priority
- 可透過 F12 > Network,右鍵點選 Table Header,將 "Priority" 勾選,即可看到
- 瀏覽器針對資源的載入順序,大致可分為 Highest > High > Medium > Low > Lowest
<link rel="alternate">
主要是為了 SEO,宣告不同語言的頁面
<link rel="alternate" hreflang="x-default" href="https://example.com/" />
<link rel="alternate" href="https://example.com/?lang=zh-TW" hreflang="zh-TW" />
x-default 是 Google 搜尋引擎定義的
<link rel="canonical">
canonical = 典範,在這邊代表的是 "preferred URL"
<link rel="canonical" href="https://example.com/" />
<link rel="dns-prefetch">
針對 cross-origin domains 先做 dns-prefetch
- same-origin 不需要,因為瀏覽器在訪問此頁面之前,就已經完整建立連線了
- dns-prefetch 的用意是,先把 domain name resolve as IP Address
<link rel="dns-prefetch" href="https://fonts.googleapis.com/" />
<link rel="preconnect">
<link rel="prefetch">
- 可以將資源的載入順序變成 "Lowest"
- 通常用在 same-origin,使用者下一頁會載入的資源
- Response Header 若含有特定 Cache-Control,例如 no-store 或是 no-cache,則 prefetch 的資源就無法存在 HTTP Cache
- Request Header 會有
Sec-Purpose: prefetch,Sec-Fetch-Dest: empty
使用 NodeJS http 模組實作:
<link rel="modulepreload">
Vite 專案會看到,主流的瀏覽器到 2023 年才全數支援
<link rel="modulepreload" href="/assets/chunks/theme.Dk-6AaEp.js" />
跟 <link rel="preload"> 的差異是
The main difference is that preload just downloads the file and stores it in the cache, while modulepreload gets the module, parses and compiles it, and puts the results into the module map so that it is ready to execute.
<link rel="preload">
- 可以將資源的載入順序變成 "High"
<link rel="preload" href="main.js" as="script" />
<link rel="preload" href="font.ttf" as="font" type="font/ttf" crossorigin />
as="font" 的情況,需要明確指定 crossorigin / crossorigin="" / crossorigin="anonymous"
<link rel="icon">
最常用的情境就是 favicon
<link rel="icon" href="favicon.ico" />
<link crossorigin>
103 early hints
edge case 1: link + Content-Type !== text/html
edge case 2: link + HTTP/1.1 Connection: closed
edge case 3: link block HTML render
edge case 3: maximum links
edge case 4: HOL Blocking
參考資料
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Link
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/103
- https://nodejs.org/api/http.html#responsewriteearlyhintshints-callback
- https://developers.cloudflare.com/cache/advanced-configuration/early-hints/
- https://datatracker.ietf.org/doc/html/rfc8297
- https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel
- https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/preconnect
- https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/preload
- https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/prefetch
- https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/modulepreload
- https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/dns-prefetch