Kết xuất trước có nghĩa là gửi mã đánh dấu của một phần tử tuỳ chỉnh (bao gồm cả cây bóng của phần tử đó) từ máy chủ, nhờ đó thành phần được tạo kiểu và cấu trúc trước khi bất kỳ JavaScript nào chạy. Thành phần gốc chính của nền tảng cho việc này là DOM tối khai báo (DSD): trình phân tích cú pháp chỉ đính kèm gốc tối từ HTML và phần tử này sau đó sẽ được nâng cấp ("hydrat hoá") theo lớp của nó nếu có một lớp được đăng ký. Sử dụng mẫu này để kết xuất phía máy chủ, truyền trực tuyến và tránh nội dung không có kiểu (FOUC).
Tạo gốc bóng khai báo
Lồng <template> có thuộc tính shadowrootmode làm thành phần con đầu tiên của máy chủ lưu trữ. Trình phân tích cú pháp đính kèm nội dung của nó dưới dạng gốc bóng và xoá mẫu; không cần tập lệnh.
<my-card>
<template shadowrootmode="open">
<style>
.card { border: 1px solid; border-radius: 8px; padding: 1rem; }
</style>
<div class="card">
<slot name="header"></slot>
<div class="body"><slot></slot></div>
</div>
</template>
<!-- Light DOM children are projected into the slots above. -->
<h2 slot="header">Server-rendered title</h2>
<p>Visible and styled before JS loads.</p>
</my-card>
Thời điểm uống nước
Khi lớp phù hợp được đăng ký, trình duyệt sẽ nâng cấp máy chủ lưu trữ. Vì gốc bóng tối đã tồn tại, nên hàm khởi tạo không được tạo một cách mù quáng một gốc bóng tối thứ hai:
class MyCard extends HTMLElement {
constructor() {
super();
// Reuse the server-rendered shadow root if present; only create one if absent.
if (!this.shadowRoot) {
this.attachShadow({ mode: 'open' });
this.shadowRoot.append(template.content.cloneNode(true));
}
// Hydrate in place: attach listeners once against existing markup (not unguarded
// in connectedCallback, which re-runs if the element moves in the DOM), and do
// NOT re-render; that would discard the server's DOM and flash.
this.shadowRoot.getElementById('toggle')
?.addEventListener('click', () => this.toggleAttribute('open'));
}
}
Đặt shadowrootmode="open" (không phải closed) cho hầu hết các trường hợp để tập lệnh và công cụ có thể truy cập vào this.shadowRoot để bổ sung dữ liệu. Để chuyển đổi tuần tự một gốc bóng hiện có trở lại HTML trên máy chủ hoặc trong các chương trình kiểm thử, hãy sử dụng getHTML({ serializableShadowRoots: true }) và đính kèm gốc bằng serializable: true.
Tránh FOUC
DSD chỉ hiển thị chính xác trong lần hiển thị đầu tiên nếu các kiểu được cung cấp bên trong mẫu khai báo. Để giữ nguyên điều đó:
- Đặt CSS của thành phần bên trong
<template shadowrootmode>(thẻ<style>hoặc<link>), chứ không phải trong một trang tính riêng biệt được tải bằng tập lệnh. - Chỉ ghép nối với
my-card:not(:defined) { … }cho những kiểu phải đợi JS – thường là các quy tắc bảo vệ ở cấp trang, chẳng hạn như hiệu ứng mờ dần trên các thực thể được kết xuất phía máy khách bị thiếu lượt truyền SSR. Các kiểu này nằm trong biểu định kiểu light-DOM (trang), vì gốc tối chưa tồn tại ở đó và bộ chọn:hostkhông áp dụng từ bên ngoài. Kiểu cấu trúc bên trong mẫu DSD không cần biện pháp bảo vệ như vậy. - Không kết xuất lại cây bóng khi hydrat hoá. Coi mã đánh dấu máy chủ là mã có thẩm quyền và đính kèm hành vi vào mã đó.
Chiến lược dự phòng
Trong các công cụ không phân tích cú pháp shadowrootmode, mẫu sẽ không hoạt động và nội dung của mẫu không được đính kèm dưới dạng gốc bóng. Phát hiện điều này (Object.hasOwn(HTMLTemplateElement.prototype, 'shadowRootMode')) và nếu không có, hãy đính kèm gốc bóng tối một cách bắt buộc từ cùng một mã đánh dấu trong quá trình nâng cấp để thành phần vẫn hiển thị.