Document Metadata (如 <title>
、<link>
和 <meta>
)會放在 HTML 的 <head>
區塊中,這部分的內容會對 SEO 和網站相關資訊的呈現很重要。
在 React 19 之前如果在 Component 內使用,會被放在 <body>
中,但通常我們會希望放在 <head>
中。通常會使用第三方 library 像是 react-helmet 或是透過框架的內建方法來解決這個問題。
在 React 19 之後,React 將自動確保與這些 Metadata 對應的 DOM 元素被正確地放置在 <head>
中。
使用範例:
function UserData({ user }) {
return (
<article>
<h1>{user.name}</h1>
<title>{user.name}'s Profile</title>
<meta name="author" content={user.name} />
<link rel="author" href={user.url} />
<meta name="description" content="user description" />
<p>{user.bio}</p>
</article>
);
}
在處理 Stylesheet 時,載入順序至關重要,因為後載入的樣式會覆蓋先載入的樣式規則。另外若初次渲染時若樣式未完全載入,會出現無樣式內容閃爍(FOUC, Flash of Unstyled Content),讓使用者體驗不好。
在 React 19 對 Stylesheet 載入進行優化,透過 Stylesheet 搭配 Suspense 可以讓 script 和 Stylesheet 載入同時進行。透過 Suspense 可以在載入 CSS 時顯示 fallback UI,當 CSS 完全載入時再顯示真正的內容。
使用範例:
function MyComponent() {
return (
<Suspense fallback="loading...">
<link rel="stylesheet" href="foo" precedence="default" />
<link rel="stylesheet" href="bar" precedence="high" />
<article class="foo-class bar-class">{/* ... */}</article>
</Suspense>
);
}
當在 <link>
使用 rel="stylesheet"
時才能使用 precedence
屬性。precedence
用來告訴 React 這個 Stylesheet 相對於其他樣式的優先級。高優先級的樣式會覆蓋低優先級的樣式,載入的結果會像下面這樣:
<html>
<head>
<link rel="stylesheet" href="bar" />
<link rel="stylesheet" href="foo" />
</head>
<body>
<!-- 其他內容 -->
</body>
</html>
除了使用 <link>
來載入樣式外,也可以使用 <style>
來載入樣式。功能都是類似的,一樣有 precedence
來告訴 React 這個樣式優先級。另外如果在不同的 Component 多次載入相同的 Stylesheet, React 也只會載入一次。
如果是正常的使用 <script>
會阻塞 HTML
解析,因為瀏覽器會在載入與執行完腳本後才繼續處理其他內容。為了避免阻塞可以使用 async
屬性來非同步加載 JavaScript 文件。
在 React 19 之前使用 Async Script 並不會保證載入順序,React 19 改進了 Async Script,可以在 Component 中載入 <script>
,並且也會去除重複載入。
使用範例:
function MyComponent() {
return (
<>
<script async src="/path/to/some/script.js" />
{/* ... */}
</>
);
}
在 React 19 也推出了許多新 API 來處理資源的 preload。React 會將這些內容放到 <head>
中,並會根據優先順序重新排序。透過 preload 可以優化初始頁面載入時間,除此之外也可以與事件處理器結合使用,讓我們在預計要切換頁面時提前加載所需資源。
preload
:用於預加載 stylesheet、字體、圖片或外部的 script。preinit
:用於提前載入 script,或插入 stylesheet。preloadModule
和 preinitModule
:這些 API 是針對 ESM module。prefetchDNS
:提前解析 DNS 資源。preconnect
:提前與伺服器建立連接。使用範例:
import { prefetchDNS, preconnect, preload, preinit } from "react-dom";
function MyComponent() {
preinit("https://.../path/to/some/script.js", { as: "script" });
preload("https://.../path/to/font.woff", { as: "font" });
preload("https://.../path/to/stylesheet.css", { as: "style" });
prefetchDNS("https://...");
preconnect("https://...");
}
參考資料:
https://www.youtube.com/watch?v=IBBN-s77YSI
https://react.dev/blog/2024/04/25/react-19
https://react.dev/reference/react-dom/components/script
https://react.dev/reference/react-dom/components/style
https://www.youtube.com/watch?v=AJOGzVygGcY