Next系統總結學習(一)

下面我按題號逐條 詳細 解釋并給出示例與最佳實踐。為便于閱讀,我會同時給出關鍵代碼片段(偽代碼/實用例子),并指出常見坑與解決方案。

1. 你是如何理解服務端渲染(SSR)的?它的核心工作流程是怎樣的?

理解(簡要):
服務端渲染(SSR,Server-Side Rendering)指在服務器端執行前端應用的渲染邏輯,生成完整或部分 HTML,然后把該 HTML 返回給瀏覽器。瀏覽器收到的不是空的 div#root,而是可見的、有語義的 HTML 內容,之后再下載并執行前端 JS,把頁面“接管”(hydrate)成為可交互的單頁應用(SPA)。

核心工作流程(高層):

  1. 瀏覽器發出 HTTP 請求(GET /path)。
  2. 服務器接收請求,基于請求 URL 做路由匹配(找到對應頁面組件/路由)。
  3. 服務器執行與該路由相關的數據獲取(同步或異步),得到初始數據/state。
  4. 服務器把組件渲染成 HTML 字符串(或流式輸出部分 HTML)。
  5. 服務器把 HTML + 初始序列化狀態(例如 window.__INITIAL_STATE__)和指向客戶端腳本的 <script> 一并返回。
  6. 瀏覽器解析 HTML(首屏內容可見),并開始并行加載 JS/CSS/資源。
  7. 客戶端 JS 執行,讀取服務器注入的初始狀態并進行 hydration,裝配事件處理器,頁面變得可交互。

關鍵點: 渲染過程發生在服務器端,渲染結果攜帶初始數據發送到客戶端;客戶端只做掛載/復用而不是從零開始渲染整棵樹。

2. 為什么需要服務端渲染?它主要解決了客戶端渲染(CSR)的哪些問題?

主要原因 / 優勢:

  • 首屏體驗(首字節到可見內容更快):用戶能更早看到內容,感知速度提升,特別是慢網或低端設備上。
  • 搜索引擎優化(SEO):搜索引擎爬蟲和社交抓取器能夠直接讀取 HTML 內容(meta、open graph),提高索引與分享預覽質量。
  • 更好的社交卡片與預覽:分享到社交平臺時,抓取器獲取的是完整 HTML meta,而非依賴 JS 才生成的內容。
  • 可訪問性 & 無 JS 場景降級:在 JavaScript 被禁用或異常情況下,用戶仍能看到內容(至少部分內容)。
  • 首屏可渲染時間(TTI/First Contentful Paint)優化:服務器返回 HTML,瀏覽器可以立即渲染,而 CSR 需要下載并執行大量 JS 才能產生可見內容。
  • 可控的資源優先級:服務器端可以內聯關鍵 CSS、預加載關鍵腳本資源,優化渲染路徑。

CSR 的痛點(SSR 主要解決或緩和):

  • CSR 初始請求通常返回空 HTML,需要下載大包 JS 才能渲染,導致首屏慢。
  • SEO 問題:早期或部分爬蟲難以執行 JS(現在好多能執行,但仍有限制)。
  • “白屏”或“閃爍”(FOUC)問題,尤其在慢網絡或 CPU 較弱設備上明顯。
  • 社交抓取/預覽無法拿到動態內容(除非額外處理)。

權衡:
SSR 提升體驗但帶來更高的后端復雜度、構建和部署復雜性、緩存策略需求、以及處理服務器上同步/并發渲染時的資源占用問題(CPU / 內存 / IO)。是否使用 SSR 取決于產品需求(SEO、首屏體驗)與工程成本。

3. 什么是“同構(Isomorphic)/通用(Universal)”代碼?在 SSR 中為何重要?

定義:
“同構/通用”代碼指同一套 JavaScript 代碼能夠在 服務器端和客戶端 兩個環境中運行 —— 例如,業務組件、路由定義、數據獲取邏輯復用在服務器渲染和客戶端渲染中。

在 SSR 中的重要性:

  • 代碼復用:同一套組件既用于服務器渲染也用于客戶端 hydration,減少重復實現和維護成本。
  • 一致性:保證服務器渲染時生成的 UI 與客戶端渲染/交互時的 UI 一致(避免 “內容不一致” 的 React 警告)。
  • 統一路由與數據獲取機制:同構路由可以在服務器上匹配并加載數據、在客戶端復用同樣的路由邏輯做客戶端導航。
  • 開發效率:開發者只需關注一套邏輯,易于測試與維護。

注意點:
同構代碼必須 避免直接依賴瀏覽器全局對象window, document, localStorage 等),或對這類依賴做運行時判斷/延遲調用(見第6點)。此外,模塊分包(server/client bundles)與構建配置需要支持不同目標的打包。

4. 請描述一次完整的 SSR 請求生命周期,從瀏覽器發出請求到頁面可交互

下面給出一個較完整、帶步驟的生命周期(包含常見中間環節與優化點):

  1. DNS/TCP/TLS/CDN(前置層)

    • 瀏覽器解析 DNS、建立 TCP/TLS 連接(若啟用 CDN,CDN 會先命中或回源)。
  2. 請求到達邊緣或應用服務器

    • CDN 緩存判斷命中:若命中直接返回緩存 HTML(最快)。否則請求到應用服務器或 Serverless 函數。
  3. 服務器/邊緣路由匹配

    • 服務端用與客戶端同構的路由邏輯匹配請求 URL,決定要渲染哪個頁面/組件樹。
  4. 數據加載(服務器上)

    • 執行路由對應的數據加載器(同步或異步),讀取 DB、調用后端 API、做鑒權等。
    • 可使用并行/復合請求并設超時與降級策略(避免無限等待)。
  5. 渲染到 HTML(server-render)

    • 將 React/Vue 等組件樹渲染成 HTML 字符串或流,并在適當位置注入初始序列化狀態(“脫水”)。
    • 可采用流式渲染:先把 shell(靜態骨架)返回,隨后逐步發送組件 HTML,縮短 Time-to-first-byte(TTFB)。
  6. 插入資源引用

    • 在返回 HTML 中包含 <link rel="stylesheet"><script src="client.js" defer>、預加載/預取 hint 等。
  7. HTTP 響應

    • 服務器將 HTML 發回瀏覽器(做 gzip/br/HTTP2 等壓縮),并可配合緩存頭(Cache-Control、ETag、Surrogate-Key)緩存策略。
  8. 瀏覽器解析 HTML

    • 瀏覽器構建 DOM / CSSOM,頁面可見(首屏已顯示)。此時仍未綁定 JS 事件。
  9. 資源并行加載

    • 瀏覽器下載 JS、CSS、圖片等資源(如果 <script> 使用 defer 或 module,則先解析后執行)。
  10. 客戶端 JS 執行與 Hydration(注水)

    • 客戶端腳本讀取服務器注入的初始 state(如 window.__INITIAL_STATE__),運行客戶端入口,執行 hydrate()hydrateRoot(),將事件處理器掛到已存在的 DOM 上,進行 DOM 比對(reconciliation)。
  11. 頁面可交互

    • hydration 完成后,路由跳轉、事件處理等全部生效;此時頁面被完全“接管”成 SPA。
  12. 后續導航(客戶端路由)

    • 之后的導航可在客戶端完成(局部更新、客戶端數據 fetch),避免再次 SSR(除非需要新頁面的 SSR)。

失敗/降級場景:

  • 數據加載失敗 -> 可返回錯誤頁面或返回帶錯誤提示的 HTML(并在客戶端 retry)。
  • Hydration 報錯 -> 瀏覽器可能會重新完全渲染客戶端(client-side render fallback),或顯示不交互的頁面。
  • 超時 -> 可設定渲染超時,返回部分 HTML(骨架)并標注 JS 在客戶端補全。

5. SSR 應用的“服務端入口”(Server Entry)和“客戶端入口”(Client Entry)有何不同?

Server Entry(服務器入口)特點:

  • 運行環境:Node.js / serverless / edge runtime(無瀏覽器 DOM)。
  • 目標:導出用于服務器渲染的接口(例如接受 URL -> 返回 HTML 字符串 / 流的函數)。
  • 不應包含瀏覽器專屬 API 的直接使用(或者要做保護判斷)。
  • 打包目標通常是 target: node,保留 require、不需要 polyfill 瀏覽器 API,通常要剔除客戶端依賴(CSS-in-JS 有時需要特定處理以抽取樣式)。
  • 可以直接訪問服務器資源(數據庫、文件系統、環境變量、后端 API)。

Client Entry(客戶端入口)特點:

  • 運行環境:瀏覽器(有 DOM、window、document)。
  • 目標:在加載時讀取服務器注入的狀態,執行 hydrate()hydrateRoot(),并啟動客戶端路由、事件綁定、熱更新(開發時)。
  • 包含瀏覽器 polyfills、第三方客戶端庫(analytics、service worker 注冊等)。
  • 通常被 code-splitting(按路由拆包)以減小初始下載體積。

不同點(對比表):

  • 運行時:Server->Node;Client->Browser
  • 包含內容:Server->渲染邏輯、數據加載器;Client->事件處理、交互邏輯、路由器、持久化。
  • 構建目標:Server->server bundle(體積可小但包含渲染需要);Client->瀏覽器 bundle(要優化大小)
  • 生命周期:Server->一次 HTTP 請求到響應;Client->頁面首載后長期駐留與導航

6. 在服務端執行前端代碼時,遇到 window 或 document 等瀏覽器特有對象不存在應如何處理?

核心策略:避免直接在模塊頂層使用瀏覽器 API;在運行時判斷或延遲在客戶端執行。

常見做法(按安全與優先級):

  1. 運行時判斷(最簡單):
const isBrowser = typeof window !== 'undefined';if (isBrowser) {// 瀏覽器獨有邏輯
}
  1. 把瀏覽器副作用放到生命周期里(React)

    • 把 DOM 相關操作放在 useEffect(只在客戶端運行),而不是 rendergetInitialProps
useEffect(() => {// 這個只會在客戶端執行const el = document.getElementById('x');
}, []);
  1. 條件/動態導入(code-splitting)

    • 延遲加載依賴瀏覽器的模塊(import()):
if (typeof window !== 'undefined') {import('some-dom-lib').then(lib => { lib.doSomething(); });
}
  1. 抽象平臺差異為“環境適配器”

    • platform 的抽象接口封裝(server 與 client 提供不同實現),依賴注入。
  2. SSR-safe 組件

    • 對需要瀏覽器 API 的組件,在 SSR 時返回占位(skeleton),在客戶端 mount 后再真正渲染。
function MapComponent() {const [mounted, setMounted] = useState(false);useEffect(()=> setMounted(true), []);if (!mounted) return <div className="map-placeholder" />;return <RealMap/>; // uses window.google.maps
}
  1. 模擬 DOM(不推薦)

    • 在某些場景(測試或特殊庫)可以用 jsdom 在 Node 上提供 documentwindow。但實際生產 SSR 中盡量避免這樣做(性能/兼容/不可控)。
  2. 安全的第三方庫選擇

    • 選那些支持 SSR 的庫(說明中標注 ssr: true 或有服務端兼容實現)。

7. Node.js 在 SSR 架構中扮演了什么角色?

Node.js 作為服務器端 JavaScript 運行時,承擔下列職責:

  • 運行 SSR 渲染代碼:執行 React/Vue/Svelte 等框架的服務器渲染 API(renderToStringrenderToPipeableStream 等)。
  • 提供 HTTP 服務:作為應用服務器(或在 serverless 中作為運行時)接收請求、路由、返回 HTML。
  • 與后端服務/數據庫交互:在渲染前獲取數據、做鑒權、調用微服務、緩存等。
  • 文件與靜態資源管理:讀取模板、發放靜態資源、構建時處理。
  • 緩存策略實現:在內存、Redis、CDN 回源層配合做頁面/片段緩存。
  • 流式輸出與性能優化:通過流(streaming)把 HTML 分塊發送給客戶端,縮短首屏時間。
  • 中間件支持:整合日志、監控、錯誤上報、安全中間件(CSP、XSS 防護)等。
  • 運行時多樣化:可以部署為長駐服務(傳統 Node 服務器),也可打包為 serverless 函數或中轉到 Edge Runtime(Cloudflare Workers、Deno、V8 isolates 等),不同環境會影響渲染模型與性能。

補充: 隨著 Edge/Worker 平臺興起,有些 SSR 工作可以在更靠近用戶的邊緣節點完成(更低延遲),但這些運行時可能不能訪問本地文件系統,也對 API 有限制(短執行時間、不同的 Node API)。

8. SSR 中的路由同構是如何實現的?

目標:服務器和客戶端使用相同的路由定義與匹配邏輯,服務器用于匹配并提前加載對應頁面的數據,客戶端用于后續導航與局部更新。

實現方法(常用模式):

  1. 定義一份“路由表/路由配置”

    • 把路由及其對應組件、數據加載器、meta 信息寫成共享配置(例如 routes.js),這個文件既被 ServerEntry 使用,也被 ClientEntry 使用。
// routes.js (示例)
export default [{ path: '/', component: Home, loader: homeLoader },{ path: '/post/:id', component: Post, loader: postLoader },
];
  1. 服務器端用路由匹配庫(matchRoutes)找到匹配項并運行 loader

    • 在服務器接收到 /post/123 時,用相同的匹配算法取得要渲染的組件和它的 loader,然后在渲染前調用 loader 獲取所需數據并注入(脫水)。
import { matchRoutes } from 'react-router';
const matches = matchRoutes(routes, req.url);
await Promise.all(matches.map(m => m.route.loader && m.route.loader({params: m.params})));
  1. 客戶端使用同一套路由定義做導航與懶加載

    • 客戶端 hydration 后,路由庫(如 React Router、Vue Router)根據同樣的配置處理 pushState 導航、懶加載組件及其數據獲取(可以使用 prefetch)。
  2. 錯誤/重定向/404 的統一處理

    • 路由的重定向或 404 處理應在服務器端和客戶端一致(例如 loader 拋出 redirectnotFound,服務器根據異常返回 302/404)。
  3. 路由級數據預取與緩存

    • Server loader 的結果被序列化到 HTML(脫水),客戶端路由在首次渲染時復用這些數據而不重復請求(減少重復請求)。

注意事項:

  • 匹配邏輯和參數解析必須保持完全一致。
  • 要考慮 SSR 中同步/異步數據加載的超時、緩存與錯誤策略。
  • 對于文件系統路由(如 Next.js / Nuxt),構建工具會自動生成可同構的路由映射。

9. 什么是“脫水”(Dehydration)和“注水”(Hydration)?

脫水(Dehydration)
指服務器在渲染后將運行時生成的數據/狀態序列化并注入到 HTML 中,通常通過一個 <script> 標簽把初始狀態寫到 window.__INITIAL_STATE__(或類似命名)。這樣客戶端在加載時可以讀取這份預置狀態,而無需在 hydration 時重新向后端拉取同樣的數據。

注水(Hydration)
客戶端讀取服務器注入的 HTML 以及脫水的狀態,然后運行框架的 hydration API(如 React 的 hydrateRoot)來復用服務端生成的 DOM,僅掛上事件監聽并完成虛擬 DOM 的首次比對,使頁面變得可交互。

示例(簡化):
服務器輸出:

<div id="root">...rendered html...</div>
<script>window.__INITIAL_STATE__ = {/* safe-serialized data */}</script>
<script src="/client.js" defer></script>

客戶端:

const state = window.__INITIAL_STATE__;
hydrateRoot(document.getElementById('root'), <App initialState={state} />);

關鍵問題與實踐:

  • 安全: 直接把 JSON 用 JSON.stringify 插入 HTML 可能導致 XSS(若數據含 </script>)。應用 serialize-javascript 或對特殊字符做轉義來避免注入攻擊。
  • 大小: 注入的數據會增加 HTML 大小,需避免傳輸過多不必要的數據(只傳必要 state)。
  • 一致性: 注入的狀態必須與服務端渲染使用的狀態一致,否則 hydration 會失敗或產生警告。
  • 部分/漸進注水(Partial/Progressive Hydration):先進的策略是只 hydrate 首屏或重要交互組件,延遲或按需 hydrate 其它部分,節省 CPU 并提升交互速度。

10. SSR 對你的開發模式和心智模型提出了哪些新的要求?

需要建立的新心智模型和開發習慣:

  1. 分清“渲染環境”與“運行環境”

    • 明確哪些代碼可在服務器運行、哪些代碼只能在瀏覽器執行(DOM 操作、瀏覽器 API、window 事件等)。
  2. 數據獲取需可在服務器端運行

    • 設計數據加載器(loaders、getServerSideProps、asyncData 等)能夠在服務器執行并返回脫水數據;并考慮網絡故障、超時與降級。
  3. 更強的錯誤/邊界意識

    • 服務器渲染中的報錯會影響 HTTP 響應,因此需要完善的錯誤邊界、超時與降級策略。要在服務端和客戶端都處理錯誤情形(并統一展示)。
  4. 緩存與性能思維

    • 需要設計頁面/片段緩存策略(CDN/邊緣/內存緩存),理解何時可以緩存和何時需要動態渲染(用戶特定內容不能緩存)。
  5. 安全意識

    • 序列化初始狀態時注意 XSS,防止敏感數據在 HTML 中泄露(例如不要把用戶密碼或秘密放進注入的 state)。
  6. 構建與部署復雜度

    • 要管理雙重構建產物(server bundle & client bundle),理解 target 配置、tree-shaking、代碼分割、CI/CD 流程的差異。
  7. 調試技巧

    • 需要同時會在服務器端和瀏覽器端調試渲染問題(server logs、stack traces、source map 配置、SSR-specific breakpoints)。
  8. 測試策略

    • 引入服務器渲染測試(例如用 renderToString 或 headless 環境測試輸出 HTML),以及客戶端 hydration 后的集成測試(確保一致性)。
  9. 漸進增強與 UX 考慮

    • 設計能在無 JS 或部分 JS 場景下也能提供合理體驗的頁面(骨架、鏈接可用、表單能工作等)。
  10. 路由/狀態統一思維

    • 將路由與數據獲取看成可以在服務端與客戶端共同驅動的流程,保證接口和約定一致。

總結性的建議:

  • 開始時把 SSR 作為優化手段(針對首屏和 SEO 的熱點頁面做 SSR),而非整個站點一次性 SSR 化。
  • 采用漸進式策略(先實現服務端渲染 + 基本脫水/注水,再優化流式渲染、緩存、部分 hydration)。
  • 選擇一個 SSR 友好的框架或工具(例如 Next.js、Nuxt、Remix、Sapper 等)可以大幅減少樣板工作并提供成熟的約定。

附:常見代碼示例(簡潔版)

服務器端(偽 Node + React 18 流式)

// server.js (node)
import express from 'express';
import { renderToPipeableStream } from 'react-dom/server';
import App from './App';
import { matchAndLoadData } from './ssr-utils'; // route match + loadersconst app = express();app.get('*', async (req, res) => {const initialState = await matchAndLoadData(req.url); // 服務器拉數據let didError = false;const stream = renderToPipeableStream(<App url={req.url} initialState={initialState} />,{onShellReady() {res.statusCode = didError ? 500 : 200;res.setHeader('Content-Type', 'text/html; charset=utf-8');res.write('<!doctype html><div id="root">');stream.pipe(res);res.write('</div>');// 安全序列化初始狀態res.write(`<script>window.__INITIAL_STATE__ = ${serialize(initialState)};</script>`);res.write('<script src="/client.js" defer></script>');res.end();},onError(err) { didError = true; console.error(err); }});
});

客戶端入口(hydrate)

// client.js
import { hydrateRoot } from 'react-dom/client';
import App from './App';const initialState = window.__INITIAL_STATE__ || {};
hydrateRoot(document.getElementById('root'), <App initialState={initialState} />);

避免 window/document 在 SSR 中報錯

// safeDom.js
export const isBrowser = typeof window !== 'undefined';
export function getWindowLocation() {return isBrowser ? window.location : { pathname: '/' };
}

你提出了關于前端渲染策略的一系列核心問題,它們確實是現代Web開發中架構選型的關鍵。下面我將為你逐一詳細解答,并配以圖表輔助說明。

📊 SSR 與 CSR 核心對比

要直觀理解服務器端渲染(SSR)和客戶端渲染(CSR)的根本區別,它們的工作流程對比是最好的方式。下圖清晰地展示了從用戶請求到頁面最終可交互的完整過程:

SSR
CSR
用戶訪問網頁
選擇渲染模式
請求發送至服務器
服務器執行邏輯
獲取數據并渲染完整HTML
返回HTML至瀏覽器
立即呈現內容
瀏覽器加載JS
進行水合Hydration
頁面可交互
服務器返回空HTML框架
與JS包
瀏覽器下載并執行JS
JS動態請求數據
并渲染頁面內容
頁面可交互

此流程決定了它們各自的特性:

特性維度服務器端渲染 (SSR)客戶端渲染 (CSR)
渲染地點服務器瀏覽器
首屏加載速度通常較快
用戶能更快看到內容
可能較慢
需等待JS下載、執行和數據加載,期間可能白屏
SEO友好性天然友好
搜索引擎可直接抓取完整HTML內容
不友好
初始HTML內容為空,依賴JS執行,不利于爬蟲抓取
服務器壓力較大
每次請求都需服務器渲染頁面
較小
服務器主要提供靜態文件和API接口
開發復雜度相對較高
需處理服務端和客戶端環境差異、水合等
相對較低
更純粹的前端開發體驗
交互體驗首屏后若需更新內容,可能需整頁刷新切換頁面體驗流暢
僅需局部更新,無需整頁刷新

🫛 12. SSR和SSG(靜態站點生成)有何區別?應如何做技術選型?

SSRSSG 都屬于預渲染策略,關鍵區別在于渲染時機

  • SSR (Server-Side Rendering)動態渲染。在用戶請求時,服務器動態獲取數據、渲染HTML并返回。適合內容頻繁變更個性化極強的頁面(如新聞詳情頁、用戶主頁)。
  • SSG (Static Site Generation)靜態生成。在項目構建時,提前將數據和模板生成靜態HTML文件。適合內容穩定的頁面(如博客、文檔、官網)。

技術選型建議

  • 選擇 SSG:若內容相對固定,追求極致性能、低服務器成本和高安全性(如技術博客、企業官網、產品文檔)。
  • 選擇 SSR:若內容動態性強,需要個性化數據或實時更新(如電商首頁、社交平臺、新聞門戶)。

🖼? 13. 什么是預渲染 (Prerendering)?它和SSR/SSG有什么關系?

  • 預渲染是一個廣義概念,指在瀏覽器呈現頁面之前,提前生成好HTML內容的過程。它主要為了解決CSR首屏慢和SEO差的問題。
  • SSR 和 SSG 是預渲染的兩種具體實現方案
    • SSG 是構建時預渲染。
    • SSR 是運行時(請求時)預渲染。

🎯 14. 在什么場景下,SSR是最佳選擇?什么場景下SSG更優?

這個選擇很大程度上取決于你內容的動態化程度和更新頻率。下圖基于這兩個維度提供了一個直觀的選型指南:

quadrantCharttitle SSR與SSG技術選型指南x-axis "低動態性" --> "高動態性"y-axis "低更新頻率" --> "高更新頻率""用戶儀表盤(高動態/實時)": [0.85, 0.9]"新聞門戶(高動態/頻繁)": [0.8, 0.7]"電商首頁(混合)": [0.65, 0.6]"商品詳情頁(混合)": [0.6, 0.5]"企業官網(靜態/穩定)": [0.2, 0.1]"技術博客(靜態/穩定)": [0.15, 0.2]"產品文檔(靜態/穩定)": [0.1, 0.3]

如圖所示,SSG靜態內容王者,非常適合企業官網、技術博客、產品文檔等內容穩定、無需用戶鑒權的場景。它能提供最快的加載速度(CDN分發)、更高的安全性和更低的服務器成本。

SSR 則擅長處理動態內容優先的場景,例如:

  • SEO依賴型頁面:新聞文章、電商商品列表頁,需要被搜索引擎收錄。
  • 重度依賴實時數據的頁面:股票行情、賽事比分。
  • 高度個性化的頁面:社交媒體信息流、用戶個人中心。

📈 15. 結合核心Web指標,分析SSR和CSR在性能表現上的差異

Core Web Vitals 是谷歌衡量用戶體驗的關鍵指標,SSR和CSR的表現差異顯著:

核心指標說明SSR 表現CSR 表現
LCP 最大內容繪制測量加載性能。感知頁面主要內容加載所需的時間。通常較好
服務器返回的HTML包含內容,LCP時間更短。
通常較差
需等待JS bundle加載執行后才會渲染內容。
FID 首次輸入延遲測量交互性。用戶首次與頁面交互到瀏覽器響應的時間。可能較差
在水合過程完成前,頁面無法響應交互。
通常較好
一旦JS加載完成,交互響應迅速。
CLS 累積布局偏移測量視覺穩定性。頁面生命周期內意外布局偏移的程度。通常較好
內容一次渲染到位,布局偏移較少。
可能較差
異步加載內容可能導致元素突然插入,造成偏移。

SSR在LCP和CLS上通常有優勢,但在FID上可能表現不佳(在水合完成前,頁面看似可見卻無法交互)。CSR則相反,其FID可能在JS加載后表現良好,但LCP和CLS通常是短板。


🔄 16. 你了解ISR(增量靜態再生)或DPR(分布式持久渲染)嗎?

它們是現代框架(如Next.js)提供的混合渲染方案,旨在結合SSG和SSR的優點:

  • ISR (Incremental Static Regeneration)

    • 解決問題:SSG無法處理動態數據,而SSR服務器壓力大。
    • 原理:在SSG基礎上,允許靜態頁面在構建后按需重新生成。你可以為頁面設置一個重新驗證時間(revalidate),過期后,下一個請求會在后臺重新生成新頁面,用戶先看到舊頁面,生成完后再更新緩存。
    • 場景:商品詳情頁、博客文章頁等數據可能變化但不需極端實時性的場景。
  • DPR 并非通用標準術語,其思想與ISR類似。


🤝 17. 混合渲染 (Hybrid Rendering) 是什么概念?

混合渲染指在同一個Web應用中,根據不同頁面的需求,混合使用SSR、SSG和CSR等多種渲染策略

  • Next.js等框架支持此概念。例如:
    • 營銷首頁(/)使用 SSG,預生成靜態文件以實現極速加載。
    • 博客文章頁(/posts/[id])使用 ISR,增量更新。
    • 用戶個人資料頁(/profile)使用 SSR,提供個性化實時內容。
    • 管理后臺(/admin/*)使用 CSR,提供豐富的交互體驗。
  • 這樣做可以在性能、新鮮度和開發成本之間取得最佳平衡

💼 18. 對于一個重交互、數據實時性要求高的后臺管理系統,適合使用SSR嗎?為什么?

通常不適合,更推薦使用CSR(或SSG+CSR)

原因如下

  1. 極重的交互性:后臺系統操作頻繁,CSR在首次加載后,后續交互無需整頁刷新,體驗極其流暢。若使用SSR,每個交互都可能請求服務器渲染,反而會犧牲響應速度
  2. 實時數據需求:數據需實時拉取和展示,CSR可通過API按需獲取和局部更新,比SSR整頁渲染更高效。
  3. 通常無SEO需求:后臺系統是權限內應用,無需被搜索引擎收錄,SSR的SEO優勢在此場景無意義
  4. 開發體驗與性能:CSR架構前后端分離更徹底,開發效率高。且所有渲染在客戶端進行,極大減輕了服務器壓力

更優方案:對這類系統,可采用 CSR + SSG 的混合模式。登錄頁可靜態化(SSG),主應用使用CSR。同時利用代碼分割懶加載等技術優化首屏加載速度。


在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/95883.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/95883.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/95883.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

房屋安全鑒定需要什么條件

房屋安全鑒定需要什么條件&#xff1a;專業流程與必備要素解析房屋安全鑒定是保障建筑使用安全的重要環節&#xff0c;它通過對建筑結構、材料性能及使用狀況的全面評估&#xff0c;為房屋的安全使用、改造或維護提供科學依據。隨著城市建筑老化及自然災害頻發&#xff0c;房屋…

現代C++:現代C++?

C語言正在走向完美&#xff0c;所以&#xff0c;C語言值得學習&#xff08;甚至研究&#xff09;&#xff0c;這些知識可以成為一切編程的基礎。然而在實踐中&#xff0c;不必全面的使用C語言的各種特性&#xff0c;而應根據工程項目的實際情況&#xff0c;適當取舍&#xff08…

【C++】哈希表實現

1. 哈希概念 哈希(hash)又稱散列&#xff0c;是?種組織數據的方式。從譯名來看&#xff0c;有散亂排列的意思。本質就是通過哈希 函數把關鍵字Key跟存儲位置建立一個映射關系&#xff0c;查找時通過這個哈希函數計算出Key存儲的位置&#xff0c;進行快速查找 1.1 直接定址法…

ai 玩游戲 llm玩街霸 大模型玩街霸 (3)

1. 開源代碼地址&#xff1a; https://github.com/OpenGenerativeAI/llm-colosseum 2. 架構&#xff1a; 3. 圖片&#xff1a; 4. 感覺還是下面的步驟&#xff1a; a. 實時理解游戲當前環境&#xff0c;英雄角色&#xff0c;英雄狀態 b. 根據當前狀態感知&#xff0c;生成英雄…

2025年滲透測試面試題總結-59(題目+回答)

安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 一、SQL注入全解 二、XSS與文件漏洞 三、服務端漏洞專題 四、職業經驗與能力評估 1、注入攻擊原理是什么…

GPT系列--類GPT2源碼剖析

無需多言&#xff0c;大家應該都用過了&#xff0c;如今都更新到GPT-5了。1. GPT-1回到2018年的NLP&#xff0c;神仙打架&#xff0c;BERT與GPT不分先后。GPT是“Generative Pre-Training”的簡稱&#xff0c;生成式的預訓練。BERT和GPT肯定是GPT難訓練&#xff0c;引用量也是B…

這是一款沒有任何限制的免費遠程手機控制手機的軟件

這是一款沒有任何限制的免費遠程手機控制手機的軟件支持安卓和蘋果1.安裝1.1被控制端安裝airdroid1.2控制端air mirror2.登錄賬號控制端和被控制端登錄同一個賬號3.控制打開控制端軟件選擇要控制的機器直接點“遠程控制“

Observability:更智能的告警來了:更快的分診、更清晰的分組和可操作的指導

作者&#xff1a;來自 Elastic Drew Post 探索 Elastic Stack 告警的最新增強功能&#xff0c;包括改進的相關告警分組、將儀表盤鏈接到告警規則&#xff0c;以及將調查指南嵌入到告警中。 在 9.1 版本中&#xff0c;我們對告警進行了重大升級&#xff0c;幫助 SRE 和運維人員更…

數智之光燃盛景 共同富裕創豐饒

8月29日&#xff0c;2025數博會“一帶一路”國際大數據產業發展暨數智賦能新時代、共同富裕向未來的會議在貴陽國際生態會議中心隆重舉行。作為全球大數據領域的重要盛會&#xff0c;此次活動吸引了來自聯合國機構、國際組織、科研院所、知名企業等社會各界的百余位代表&#x…

【網絡編程】recv函數的本質是什么?

一、為什么說recv函數的本質是 “copy”&#xff1f; recv是用于從網絡連接&#xff08;或其他 IO 對象&#xff09;接收數據的函數&#xff0c;它的核心動作不是 “從網絡上拉取數據”&#xff0c;而是 “把已經到達內核緩沖區的數據復制到用戶程序的緩沖區”。 具體流程拆解&…

JSP程序設計之輸入/輸出對象 — out對象

目錄1、out對象概述2.實例&#xff1a;out對象方法運用輸入/輸出對象&#xff0c;可以控制頁面的輸入和輸出&#xff0c;用于訪問與所有請求和響應有關的數據&#xff0c;包括out、request和response對象。 1、out對象概述 out對象是JspWriter類的一個實例&#xff0c;是一個…

UE里為什么要有提升變量

1、為了簡潔當一個類里面的函數比較多&#xff0c;并且使用比較頻繁的時候&#xff0c;就要不斷的從這個類節點往外拉線&#xff0c;從而獲取不同的函數節點&#xff0c;這樣的藍圖就會看起來比較亂&#xff0c;這時候&#xff0c;就可以將這個常用的類提升為變量。2、為了存儲…

玩轉物聯網只需十行代碼,可它為何悄悄停止維護

文章目錄玩轉物聯網只需十行代碼&#xff0c;可它為何悄悄停止維護1 背景&#xff1a;MQTT 遇上 asyncio&#xff0c;為什么選 hbmqtt&#xff1f;2 hbmqtt 是什么&#xff1f;3 安裝&#xff1a;一行命令&#xff0c;但別裝最新4 五大核心 API&#xff1a;10 行代碼跑通發布訂…

從零開始學大模型之預訓練語言模型

預訓練語言模型 本文較長&#xff0c;建議點贊收藏&#xff0c;以免遺失。更多AI大模型開發 學習視頻/籽料/面試題 都在這>>Github<< >>Gitee<< 3.1 Encoder-only PLM 在上一章&#xff0c;我們詳細講解了給 NLP 領域帶來巨大變革注意力機制以及使用…

JMeter接口測試全流程解析

1. Jmeter的界面介紹和功能組件&#xff08;元件&#xff09;1、測試計劃&#xff1a;Jmeter的起點和容器2、線程組&#xff1a;代表一定的虛擬用戶&#xff08;一個用戶一個線程&#xff09;3、取樣器&#xff1a;發送請求的最小單元4、邏輯控制器&#xff1a;控制組件的執行順…

Effective Modern C++ 條款26:避免在通用引用上重載

在C編程中&#xff0c;函數重載是一項強大的特性&#xff0c;它允許我們為不同的參數類型提供不同的實現。然而&#xff0c;當涉及到通用引用&#xff08;universal references&#xff09;時&#xff0c;重載可能會帶來意想不到的問題。Effective Modern C的條款26明確指出&am…

OpenLayers數據源集成 -- 章節一:圖像圖層詳解

前言在前面的文章中&#xff0c;我們學習了OpenLayers的基礎控件操作。本文將深入探討OpenLayers中的圖像圖層&#xff08;ImageLayer&#xff09;功能&#xff0c;通過一個完整的示例來展示如何使用ImageArcGISRest數據源加載ArcGIS服務&#xff0c;并詳細解釋圖層配置、事件監…

通義萬相wan2.2 Fun系列--Camera鏡頭控制與lnp首尾幀視頻模型

上節內容講解了wan2.2 fun control本節內容對wan2.2 fun系列模型的camera鏡頭控制模型與lnp首尾幀視頻模型進行測試與講解。 Wan2.2-Fun-Camera-Control是阿里基于Wan2.2框架推出的圖生視頻運鏡控制模型 。它支持512、768、1024等多分辨率的視頻預測&#xff0c;以81幀、每秒16…

JavaSE 集合從入門到面試:全面解析與實戰指南

JavaSE 集合從入門到面試&#xff1a;全面解析與實戰指南 在 Java 編程中&#xff0c;集合是處理數據的核心工具&#xff0c;幾乎所有 Java 應用都會用到集合框架。從簡單的列表存儲到復雜的數據分析&#xff0c;集合框架提供了豐富的數據結構和操作方法。本文將從基礎概念到面…

自建云音樂服務器:Navidrome+cpolar讓無損音樂隨身聽

文章目錄前言1. 安裝Docker2. 創建并啟動Navidrome容器3. 公網遠程訪問本地Navidrome3.1 內網穿透工具安裝3.2 創建遠程連接公網地址3.3 使用固定公網地址遠程訪問前言 “想聽自己的無損音樂還要開會員&#xff1f;”——音樂發燒友小王的煩惱。商業音樂平臺音質壓縮&#xff…