VUE SSR(服務端渲染)

在這里插入圖片描述

🤖 作者簡介:水煮白菜王,一位前端勸退師 👻
👀 文章專欄: 前端專欄 ,記錄一下平時在博客寫作中,總結出的一些開發技巧和知識歸納總結?。
感謝支持💕💕💕

目錄

  • 總覽
    • 什么是 SSR?
    • 為什么要用 SSR?
    • SSR vs. SSG
  • 基礎教程
    • 渲染一個應用
    • 客戶端激活
    • 代碼結構
  • 更通用的解決方案
    • Nuxt
    • Quasar?
    • Vite SSR?
  • 書寫 SSR 友好的代碼
    • 服務端的響應性
    • 組件生命周期鉤子
    • 訪問平臺特有 API
    • 跨請求狀態污染
    • 激活不匹配?
    • 消除激活不匹配
    • 自定義指令
    • Teleports
  • 服務器渲染難點與亮點

本文將基于Vue官方提供的介紹進行切入,詳細復述Vue文檔SSR的相關知識點為基礎 😀。之后進行梳理并總結SSR服務器渲染知識,總結SSR在實際實施時一些難點和亮點 🚀。

總覽

什么是 SSR?

Vue.js 是一個用于構建客戶端應用的框架。默認情況下,Vue 組件的職責是在瀏覽器中生成和操作 DOM。然而,Vue 也支持將組件在服務端直接渲染成 HTML 字符串,作為服務端響應返回給瀏覽器,最后在瀏覽器端將靜態的 HTML“激活”(hydrate) 為能夠交互的客戶端應用。

一個由服務端渲染的 Vue.js 應用也可以被認為是“同構的”(Isomorphic) 或“通用的”(Universal),因為應用的大部分代碼同時運行在服務端和客戶端。

為什么要用 SSR?

與客戶端的單頁應用 (SPA) 相比,SSR 的優勢主要在于:

  • 更快的首屏加載:這一點在慢網速或者運行緩慢的設備上尤為重要。服務端渲染的 HTML 無需等到所有的 JavaScript
    都下載并執行完成之后才顯示,所以你的用戶將會更快地看到完整渲染的頁面。除此之外,數據獲取過程在首次訪問時在服務端完成,相比于從客戶端獲取,可能有更快的數據庫連接。這通常可以帶來更高的核心
    Web 指標評分、更好的用戶體驗,而對于那些“首屏加載速度與轉化率直接相關”的應用來說,這點可能至關重要。

  • 統一的心智模型:你可以使用相同的語言以及相同的聲明式、面向組件的心智模型來開發整個應用,而不需要在后端模板系統和前端框架之間來回切換。

  • 更好的 SEO:搜索引擎爬蟲可以直接看到完全渲染的頁面。

截至目前,Google 和 Bing 可以很好地對同步 JavaScript 應用進行索引。這里的“同步”是關鍵詞。如果你的應用以一個 loading 動畫開始,然后通過 Ajax 獲取內容,爬蟲并不會等到內容加載完成再抓取。也就是說,如果 SEO 對你的頁面至關重要,而你的內容又是異步獲取的,那么 SSR 可能是必需的。

使用 SSR 時還有一些權衡之處需要考量:

  • 開發中的限制。瀏覽器端特定的代碼只能在某些生命周期鉤子中使用;一些外部庫可能需要特殊處理才能在服務端渲染的應用中運行。

  • 更多的與構建配置和部署相關的要求。服務端渲染的應用需要一個能讓 Node.js 服務器運行的環境,不像完全靜態的 SPA 那樣可以部署在任意的靜態文件服務器上。

  • 更高的服務端負載。在 Node.js 中渲染一個完整的應用要比僅僅托管靜態文件更加占用 CPU 資源,因此如果你預期有高流量,請為相應的服務器負載做好準備,并采用合理的緩存策略。

在為你的應用使用 SSR 之前,你首先應該問自己是否真的需要它。這主要取決于首屏加載速度對應用的重要程度。例如,如果你正在開發一個內部的管理面板,初始加載時的那額外幾百毫秒對你來說并不重要,這種情況下使用 SSR 就沒有太多必要了。然而,在內容展示速度極其重要的場景下,SSR 可以盡可能地幫你實現最優的初始加載性能。

SSR vs. SSG

靜態站點生成 (Static-Site Generation,縮寫為 SSG),也被稱為預渲染,是另一種流行的構建快速網站的技術。如果用服務端渲染一個頁面所需的數據對每個用戶來說都是相同的,那么我們可以只渲染一次,提前在構建過程中完成,而不是每次請求進來都重新渲染頁面。預渲染的頁面生成后作為靜態 HTML 文件被服務器托管。

SSG 保留了和 SSR 應用相同的性能表現:它帶來了優秀的首屏加載性能。同時,它比 SSR 應用的花銷更小,也更容易部署,因為它輸出的是靜態 HTML 和資源文件。這里的關鍵詞是靜態:SSG 僅可以用于提供靜態數據的頁面,即數據在構建期間就是已知的,并且在多次請求之間不能被改變。每當數據變化時,都需要重新部署。

如果你調研 SSR 只是為了優化為數不多的營銷頁面的 SEO (例如 //about/contact 等),那么你可能需要 SSG 而不是 SSR。SSG 也非常適合構建基于內容的網站,比如文檔站點或者博客。事實上,你現在正在閱讀的這個網站就是使用 VitePress 靜態生成的,它是一個由 Vue 驅動的靜態站點生成器。

基礎教程

渲染一個應用

  1. 創建一個新的文件夾,cd 進入
  2. 執行 npm init -y
  3. package.json 中添加 “type”: “module” 使 Node.js 以 ES modules mode 運行
  4. 執行 npm install vue
  5. 創建一個 example.js 文件:
// 此文件運行在 Node.js 服務器上
import { createSSRApp } from 'vue'
// Vue 的服務端渲染 API 位于 `vue/server-renderer` 路徑下
import { renderToString } from 'vue/server-renderer'const app = createSSRApp({data: () => ({ count: 1 }),template: `<button @click="count++">{{ count }}</button>`
})renderToString(app).then((html) => {console.log(html)
})

接著運行:

> node example.js

它應該會在命令行中打印出如下內容:

<button>1</button>

renderToString() 接收一個 Vue 應用實例作為參數,返回一個 Promise,當 Promise resolve 時得到應用渲染的 HTML。當然你也可以使用 Node.js Stream API 或者 Web Streams API 來執行流式渲染。查看 SSR API 參考獲取完整的相關細節。

然后我們可以把 Vue SSR 的代碼移動到一個服務器請求處理函數里,它將應用的 HTML 片段包裝為完整的頁面 HTML。接下來的幾步我們將會使用 express:

  • 執行 npm install express
  • 創建下面的 server.js 文件:
import express from 'express'
import { createSSRApp } from 'vue'
import { renderToString } from 'vue/server-renderer'const server = express()server.get('/', (req, res) => {const app = createSSRApp({data: () => ({ count: 1 }),template: `<button @click="count++">{{ count }}</button>`})renderToString(app).then((html) => {res.send(`<!DOCTYPE html><html><head><title>Vue SSR Example</title></head><body><div id="app">${html}</div></body></html>`)})
})server.listen(3000, () => {console.log('ready')
})

最后,執行 node server.js,訪問 http://localhost:3000。你應該可以看到頁面中的按鈕了。

在 StackBlitz 上試試

客戶端激活

如果你點擊該按鈕,你會發現數字并沒有改變。這段 HTML 在客戶端是完全靜態的,因為我們沒有在瀏覽器中加載 Vue。

為了使客戶端的應用可交互,Vue 需要執行一個激活步驟。在激活過程中,Vue 會創建一個與服務端完全相同的應用實例,然后將每個組件與它應該控制的 DOM 節點相匹配,并添加 DOM 事件監聽器。

為了在激活模式下掛載應用,我們應該使用 createSSRApp() 而不是 createApp():

// 該文件運行在瀏覽器中
import { createSSRApp } from 'vue'const app = createSSRApp({// ...和服務端完全一致的應用實例
})// 在客戶端掛載一個 SSR 應用時會假定
// HTML 是預渲染的,然后執行激活過程,
// 而不是掛載新的 DOM 節點
app.mount('#app')

代碼結構

想想該如何在客戶端復用服務端的應用實現。這時就需要開始考慮 SSR 應用中的代碼結構了——如何在服務器和客戶端之間共享相同的應用代碼呢?

這里將演示最基礎的設置。首先,將應用的創建邏輯拆分到一個單獨的文件 app.js 中:

// app.js (在服務器和客戶端之間共享)
import { createSSRApp } from 'vue'export function createApp() {return createSSRApp({data: () => ({ count: 1 }),template: `<button @click="count++">{{ count }}</button>`})
}

該文件及其依賴項在服務器和客戶端之間共享——我們稱它們為通用代碼。編寫通用代碼時有一些注意事項,我們將在下面討論。

我們在客戶端入口導入通用代碼,創建應用并執行掛載:

// client.js
import { createApp } from './app.js'createApp().mount('#app')

服務器在請求處理函數中使用相同的應用創建邏輯:

// server.js (不相關的代碼省略)
import { createApp } from './app.js'server.get('/', (req, res) => {const app = createApp()renderToString(app).then(html => {// ...})
})

此外,為了在瀏覽器中加載客戶端文件,我們還需要:

  1. server.js 中添加 server.use(express.static('.')) 來托管客戶端文件。
  2. <script type="module" src="/client.js"></script> 添加到 HTML 外殼以加載客戶端入口文件。
  3. 通過在 HTML 外殼中添加 Import Map 以支持在瀏覽器中使用 import * from 'vue'

在 StackBlitz 上嘗試完整的示例。按鈕現在可以交互了!

更通用的解決方案

從上面的例子到一個生產就緒的 SSR 應用還需要很多工作。我們將需要:

  • 支持 Vue 單文件組件且滿足其他構建步驟要求。事實上,我們需要為同一個應用執行兩次構建過程:一次用于客戶端,一次用于服務器。

Vue 組件用在 SSR 時的編譯產物不同——模板被編譯為字符串拼接而不是 render 函數,以此提高渲染性能。

  • 在服務器請求處理函數中,確保返回的 HTML 包含正確的客戶端資源鏈接和最優的資源加載提示 (如 prefetch 和 preload)。我們可能還需要在 SSR 和 SSG 模式之間切換,甚至在同一個應用中混合使用這兩種模式。

  • 以一種通用的方式管理路由、數據獲取和狀態存儲。
    完整的實現會非常復雜,并且取決于你選擇使用的構建工具鏈。因此,我們強烈建議你使用一種更通用的、更集成化的解決方案,幫你抽象掉那些復雜的東西。下面推薦幾個 Vue 生態中的 SSR 解決方案。

Nuxt

Nuxt 是一個構建于 Vue 生態系統之上的全棧框架,它為編寫 Vue SSR 應用提供了絲滑的開發體驗。更棒的是,你還可以把它當作一個靜態站點生成器來用!我們強烈建議你試一試。

Quasar?

Quasar 是一個基于 Vue 的完整解決方案,它可以讓你用同一套代碼庫構建不同目標的應用,如 SPA、SSR、PWA、移動端應用、桌面端應用以及瀏覽器插件。除此之外,它還提供了一整套 Material Design 風格的組件庫。

Vite SSR?

Vite 提供了內置的 Vue 服務端渲染支持,但它在設計上是偏底層的。如果你想要直接使用 Vite,可以看看 vite-plugin-ssr,一個幫你抽象掉許多復雜細節的社區插件。

你也可以在這里查看一個使用手動配置的 Vue + Vite SSR 的示例項目,以它作為基礎來構建。請注意,這種方式只有在你有豐富的 SSR 和構建工具經驗,并希望對應用的架構做深入的定制時才推薦使用。

書寫 SSR 友好的代碼

無論你的構建配置或頂層框架的選擇如何,下面的原則在所有 Vue SSR 應用中都適用。

服務端的響應性

在 SSR 期間,每一個請求 URL 都會映射到我們應用中的一個期望狀態。因為沒有用戶交互和 DOM 更新,所以響應性在服務端是不必要的。為了更好的性能,默認情況下響應性在 SSR 期間是禁用的。

組件生命周期鉤子

因為沒有任何動態更新,所以像 mounted 或者 updated 這樣的生命周期鉤子不會在 SSR 期間被調用,而只會在客戶端運行。只有 beforeCreatecreated 這兩個鉤子會在 SSR 期間被調用。

你應該避免在 beforeCreatecreated中使用會產生副作用且需要被清理的代碼。這類副作用的常見例子是使用 setInterval 設置定時器。我們可能會在客戶端特有的代碼中設置定時器,然后在 beforeUnmountunmounted 中清除。然而,由于 unmount 鉤子不會在 SSR 期間被調用,所以定時器會永遠存在。為了避免這種情況,請將含有副作用的代碼放到 mounted 中。

訪問平臺特有 API

通用代碼不能訪問平臺特有的 API,如果你的代碼直接使用了瀏覽器特有的全局變量,比如 windowdocument,他們會在 Node.js 運行時報錯,反過來也一樣。

對于在服務器和客戶端之間共享,但使用了不同的平臺 API 的任務,建議將平臺特定的實現封裝在一個通用的 API 中,或者使用能為你做這件事的庫。例如你可以使用 node-fetch 在服務端和客戶端使用相同的 fetch API。

對于瀏覽器特有的 API,通常的方法是在僅客戶端特有的生命周期鉤子中惰性地訪問它們,例如 mounted

請注意,如果一個第三方庫編寫時沒有考慮到通用性,那么要將它集成到一個 SSR 應用中可能會很棘手。你或許可以通過模擬一些全局變量來讓它工作,但這只是一種 hack 手段并且可能會影響到其他庫的環境檢測代碼。

跨請求狀態污染

在狀態管理一章中,我們介紹了一種使用響應式 API 的簡單狀態管理模式。而在 SSR 環境中,這種模式需要一些額外的調整。

上述模式在一個 JavaScript 模塊的根作用域中聲明共享的狀態。這是一種單例模式——即在應用的整個生命周期中只有一個響應式對象的實例。這在純客戶端的 Vue 應用中是可以的,因為對于瀏覽器的每一個頁面訪問,應用模塊都會重新初始化。

然而,在 SSR 環境下,應用模塊通常只在服務器啟動時初始化一次。同一個應用模塊會在多個服務器請求之間被復用,而我們的單例狀態對象也一樣。如果我們用單個用戶特定的數據對共享的單例狀態進行修改,那么這個狀態可能會意外地泄露給另一個用戶的請求。我們把這種情況稱為跨請求狀態污染。

從技術上講,我們可以在每個請求上重新初始化所有 JavaScript 模塊,就像我們在瀏覽器中所做的那樣。但是,初始化 JavaScript 模塊的成本可能很高,因此這會顯著影響服務器性能。

推薦的解決方案是在每個請求中為整個應用創建一個全新的實例,包括 router 和全局 store。然后,我們使用應用層級的 provide 方法來提供共享狀態,并將其注入到需要它的組件中,而不是直接在組件中將其導入:

// app.js (在服務端和客戶端間共享)
import { createSSRApp } from 'vue'
import { createStore } from './store.js'// 每次請求時調用
export function createApp() {const app = createSSRApp(/* ... */)// 對每個請求都創建新的 store 實例const store = createStore(/* ... */)// 提供應用級別的 storeapp.provide('store', store)// 也為激活過程暴露出 storereturn { app, store }
}

像 Pinia 這樣的狀態管理庫在設計時就考慮到了這一點。請參考 Pinia 的 SSR 指南以了解更多細節。

激活不匹配?

如果預渲染的 HTML 的 DOM 結構不符合客戶端應用的期望,就會出現激活不匹配。最常見的激活不匹配是以下幾種原因導致的:

  1. 組件模板中存在不符合規范的 HTML 結構,渲染后的 HTML 被瀏覽器原生的 HTML 解析行為糾正導致不匹配。舉例來說,一個常見的錯誤是 <div > 不能被放在 <p> 中:
<p><div>hi</div></p>

如果我們在服務器渲染的 HTML 中出現這樣的代碼,當遇到 <div > 時,瀏覽器會結束第一個 <p>,并解析為以下 DOM 結構:

<p></p>
<div>hi</div>
<p></p>
  1. 渲染所用的數據中包含隨機生成的值。由于同一個應用會在服務端和客戶端執行兩次,每次執行生成的隨機數都不能保證相同。避免隨機數不匹配有兩種選擇:
    2-1 利用 v-if + onMounted 讓需要用到隨機數的模板只在客戶端渲染。你所用的上層框架可能也會提供簡化這個用例的內置 API,比如 VitePress 的 <ClientOnly> 組件。
    2-2 使用一個能夠接受隨機種子的隨機數生成庫,并確保服務端和客戶端使用同樣的隨機數種子 (比如把種子包含在序列化的狀態中,然后在客戶端取回)。
  2. 服務端和客戶端的時區不一致。有時候我們可能會想要把一個時間轉換為用戶的當地時間,但在服務端的時區跟用戶的時區可能并不一致,我們也并不能可靠的在服務端預先知道用戶的時區。這種情況下,當地時間的轉換也應該作為純客戶端邏輯去執行。

當 Vue 遇到激活不匹配時,它將嘗試自動恢復并調整預渲染的 DOM 以匹配客戶端的狀態。這將導致一些渲染性能的損失,因為需要丟棄不匹配的節點并渲染新的節點,但大多數情況下,應用應該會如預期一樣繼續工作。盡管如此,最好還是在開發過程中發現并避免激活不匹配。

消除激活不匹配

在 Vue 3.5+ 中,可以使用 data-allow-mismatch attribute 有選擇性地消除無法避免的激活不匹配警告。

自定義指令

因為大多數的自定義指令都包含了對 DOM 的直接操作,所以它們會在 SSR 時被忽略。但如果你想要自己控制一個自定義指令在 SSR 時應該如何被渲染 (即應該在渲染的元素上添加哪些 attribute),你可以使用 getSSRProps 指令鉤子:

const myDirective = {mounted(el, binding) {// 客戶端實現:// 直接更新 DOMel.id = binding.value},getSSRProps(binding) {// 服務端實現:// 返回需要渲染的 prop// getSSRProps 只接收一個 binding 參數return {id: binding.value}}
}

Teleports

在 SSR 的過程中 Teleport 需要特殊處理。如果渲染的應用包含 Teleport,那么其傳送的內容將不會包含在主應用渲染出的字符串中。在大多數情況下,更推薦的方案是在客戶端掛載時條件式地渲染 Teleport。

如果你需要激活 Teleport 內容,它們會暴露在服務端渲染上下文對象的 teleports 屬性下:

const ctx = {}
const html = await renderToString(app, ctx)console.log(ctx.teleports) // { '#teleported': 'teleported content' }

跟主應用的 HTML 一樣,你需要自己將 Teleport 對應的 HTML 嵌入到最終頁面上的正確位置處。

請避免在 SSR 的同時把 Teleport 的目標設為 body——通常 <body> 會包含其他服務端渲染出來的內容,這會使得 Teleport 無法確定激活的正確起始位置。
推薦用一個獨立的只包含 teleport 的內容的容器,例如 <div id="teleported"></div>

服務器渲染難點與亮點

Vue SSR(服務端渲染)對 SEO(搜索引擎優化)有明顯的優勢,因為它可以直接將完整的 HTML 頁面返回給搜索引擎爬蟲,這樣爬蟲能夠更好地解析頁面內容,提升 SEO 排名。然而,實際實施時也有一些難點和亮點。

難點:

  1. SSR 與 CSR 之間的同步問題: Vue SSR 渲染的是服務器端的靜態 HTML 頁面,前端會在加載后通過客戶端的 Vue 實例來激活動態功能(例如,交互)。這種雙重渲染可能會導致“閃爍”或內容的不同步,即頁面在加載時先顯示服務器渲染的內容,然后再切換到客戶端渲染的內容。這種過程可能會影響用戶體驗,甚至可能被搜索引擎誤判為無效內容。
  2. 緩存策略: 由于 Vue SSR 是在服務器上動態渲染的,如何緩存頁面內容成為一個問題。沒有合適的緩存機制,頁面的渲染會導致性能瓶頸。為了提高渲染速度,可能需要在服務器端做動態內容的緩存或靜態化處理。
  3. SEO 數據注入問題: 在 Vue SSR 中,頁面內容是動態渲染的,可能涉及到在組件加載之前就需要將 SEO 相關的元數據(如標題、描述、關鍵詞等)注入到頁面中。如果這些數據沒有在服務端渲染時注入,爬蟲可能無法獲取到正確的信息,從而影響 SEO。
  4. 環境配置與構建復雜性: Vue SSR 配置相對復雜,需要使用 Node.js 作為服務器端,合理配置 Webpack、Babel 等構建工具,以保證服務端和客戶端的代碼都能正常工作。調試和開發過程中,可能需要同時關注客戶端和服務端的日志,調試難度較大。

亮點:

  1. SEO 優化: SSR 最直接的亮點是其對 SEO 的增強。搜索引擎可以直接抓取到完整的 HTML 頁面,提升了爬蟲的可見性和頁面的索引速度,避免了傳統客戶端渲染(CSR)中爬蟲無法解析 JavaScript 內容的問題。
  2. 初次加載性能: 由于服務器渲染的頁面可以直接呈現給用戶,瀏覽器渲染時不需要等待 JavaScript 加載并執行,從而提高了頁面的首屏加載速度,提升了用戶體驗和搜索引擎的評價。
  3. 統一的渲染邏輯: 使用 Vue SSR 時,可以在客戶端和服務端共享同一套組件和渲染邏輯。這樣,開發者只需要寫一次代碼,而不需要分別為客戶端和服務端維護兩套邏輯,減少了開發工作量和出錯的可能性。
  4. 增強的用戶體驗: 由于頁面內容由服務器端直接返回,用戶能夠更快地看到完整的頁面內容,尤其在移動端和網絡較慢的情況下,SSR 可以有效提升頁面加載速度,減少閃屏和白屏現象。

Vue SSR 的 Node 中間層服務作為服務端渲染的核心部分,它在應用的部署和維護上有一些特有的難點,主要集中在以下幾個方面:

難點:

  1. Node 服務的部署和擴展性: Vue SSR 的中間層通常使用 Node.js 進行渲染,因此部署的架構需要保證 Node 服務能夠高效運行。這意味著:
    ○ 負載均衡:在高并發的情況下,需要通過負載均衡策略分發請求到多個 Node 實例。如果使用的是單機部署,性能會受到瓶頸限制。
    ○ 容器化和編排:現代部署中,使用 Docker 容器化和 Kubernetes 編排已成為常見的做法,但這也增加了運維的復雜度。需要合理設計服務的容器配置和資源調度。
  2. 服務器端渲染的性能優化:
    ○ 緩存策略:SSR 會帶來較高的計算負載,尤其是對于動態數據多的頁面。為了減少服務器的負擔,可能需要實現頁面或數據的緩存策略。例如,緩存渲染后的 HTML、API 請求結果等。
    ○ 數據預加載和異步處理:確保 SSR 時可以高效預加載必要的數據,避免頁面加載時因數據請求而造成延遲。如何合理安排數據加載的順序和方式也會影響性能。
  3. Node 服務的狀態管理與全局性問題:
    ○ 在 Node.js 中,服務端渲染需要保證請求之間的隔離性,避免數據污染和狀態混亂。SSR 渲染過程會共享同一個服務器進程,因此要確保每次請求的渲染不會互相干擾。
    ○ 全局狀態的處理:例如,Vuex 狀態管理需要特別注意服務端渲染時的狀態注入和恢復。狀態需要在服務端渲染完成后正確傳遞到客戶端,避免出現數據不一致的問題。
  4. 錯誤監控與日志管理:
    ○ SSR 渲染過程中可能會遇到各種錯誤,包括網絡請求失敗、渲染異常、模板渲染錯誤等。需要確保有完善的錯誤監控和日志收集機制(例如:Sentry、LogRocket 等)。
    ○ 實時日志:因為 Node 服務器是動態渲染內容,無法像傳統靜態頁面那樣通過簡單的調試獲取詳細的日志,所以維護過程需要實時的錯誤監控和日志記錄,幫助開發人員快速定位問題。
  5. 熱更新和部署管理:
    ○ 代碼熱更新:SSR 服務需要支持開發和生產環境中的熱更新(Hot Module Replacement,HMR)。這對于在開發過程中快速調試、調優至關重要,但也增加了開發與部署過程中的復雜性。
    ○ 部署與滾動更新:在 Node 服務上線時,通常使用滾動更新(Rolling Update)策略,避免全量下線。這要求在部署時確保 Node 服務不會造成停機時間,且能夠平穩地進行版本更新。
  6. 依賴管理與版本兼容:
    ○ 在服務端渲染的場景下,Node 服務需要處理大量的依賴庫(如 Vue、webpack、babel 等),如果依賴版本不兼容,可能會導致渲染出錯。需要定期檢查依賴關系并進行版本更新。
    ○ 服務器的 Node 環境和前端項目的依賴環境需保持一致,以避免開發和生產環境之間的差異影響渲染結果。

亮點與解決方案:

  1. 使用 Docker 容器化部署:
    ○ 通過容器化,將 Node 中間層服務封裝成 Docker 鏡像,確保開發、測試和生產環境的一致性。
    ○ 可以借助 Kubernetes 或 Docker Compose 管理多實例服務的擴展、負載均衡、健康檢查等,提高部署的靈活性和可維護性。
  2. 使用 CDN 和緩存策略:
    ○ 針對 SSR 輸出的 HTML,可以結合 CDN 來緩存靜態頁面內容,減少服務器壓力。對于動態內容,可以使用服務端緩存(例如 Redis)來緩存 API 請求結果或渲染后的頁面,從而減少重復渲染的負載。
  3. 利用現代 CI/CD 工具鏈:
    ○ 使用 GitLab CI、GitHub Actions 或 Jenkins 等 CI/CD 工具,自動化構建、測試、部署和上線流程。部署時結合藍綠發布(Blue-Green Deployment)策略,可以平滑地進行版本更新,避免服務停機。
  4. 使用日志管理與監控工具:
    ○ 集成日志管理工具(如 ELK Stack、Prometheus、Grafana)對 SSR 服務進行實時監控,確保能夠及時發現并解決潛在的問題。
    ○ 在生產環境中啟用錯誤跟蹤工具(如 Sentry),實時捕捉并報告錯誤,減少運維和開發人員的排查時間。
  5. 服務端渲染框架的優化:
    ○ 借助像 Nuxt.js 這樣的 SSR 框架,它自帶了許多性能優化和開發便利工具,能大大簡化 Vue SSR 服務端渲染的配置和部署過程,并提供內置的緩存機制和熱更新功能。

維護中的注意事項:

  • 性能監控:定期檢查 SSR 服務的性能指標,監控響應時間、吞吐量、服務器負載等,確保服務的健康運行。
  • 日志清理:由于 SSR 服務可能會生成大量日志文件,需要定期清理或歸檔日志文件,以免占用過多存儲資源。
  • 安全性:確保服務端渲染的過程中不暴露敏感數據,防止 SSR 漏洞,如跨站腳本(XSS)、跨站請求偽造(CSRF)等。

如果你的項目同樣采用了SSR架構,,是否在部署和維護過程中遇到具體的難題?

在這里插入圖片描述
如果你覺得這篇文章對你有幫助,請點贊 👍、收藏 👏 并關注我!👀
在這里插入圖片描述

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

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

相關文章

ARCGIS國土超級工具集1.5更新說明

ARCGIS國土超級工具集V1.5版本更新說明&#xff1a;因作者近段時間工作比較忙及正在編寫ARCGISPro國土超級工具集&#xff08;截圖附后&#xff09;的原因&#xff0c;故本次更新為小更新&#xff08;沒有增加新功能&#xff0c;只更新了已有的工具&#xff09;。本次更新主要修…

劉鑫煒履新共工新聞社新媒體研究院院長,賦能媒體融合新征程

2025年4月18日&#xff0c;大灣區經濟網戰略媒體共工新聞社正式對外宣布一項重要人事任命&#xff1a;聘任螞蟻全媒體總編劉鑫煒為新媒體研究院第一任院長。這一舉措&#xff0c;無疑是對劉鑫煒在新媒體領域卓越專業能力與突出行業貢獻的又一次高度認可&#xff0c;也預示著共工…

java基礎從入門到上手(九):Java - List、Set、Map

一、List集合 List 是一種用于存儲有序元素的集合接口&#xff0c;它是 java.util 包中的一部分&#xff0c;并且繼承自 Collection 接口。List 接口提供了多種方法&#xff0c;用于按索引操作元素&#xff0c;允許元素重復&#xff0c;并且保持插入順序。常用的 List 實現類包…

UWP發展歷程

通用Windows平臺(UWP)發展歷程 引言 通用Windows平臺(Universal Windows Platform, UWP)是微軟為實現"一次編寫&#xff0c;處處運行"的愿景而打造的現代應用程序平臺。作為微軟統一Windows生態系統的核心戰略組成部分&#xff0c;UWP代表了從傳統Win32應用向現代應…

git忽略已跟蹤的文件/指定文件

在項目開發中&#xff0c;有時候我們并不需要git跟蹤所有文件&#xff0c;而是需要忽略掉某些指定的文件或文件夾&#xff0c;怎么操作呢&#xff1f;我們分兩種情況討論&#xff1a; 1. 要忽略的文件之前并未被git跟蹤 這種情況常用的方法是在項目的根目錄下創建和編輯.gitig…

AI 組件庫是什么?如何影響UI的開發?

AI組件庫是基于人工智能技術構建的、面向用戶界面&#xff08;UI&#xff09;開發的預制模塊集合。它們結合了傳統UI組件&#xff08;如按鈕、表單、圖表&#xff09;與AI能力&#xff08;如機器學習、自然語言處理、計算機視覺&#xff09;&#xff0c;旨在簡化開發流程并增強…

【Win】 cmd 執行curl命令時,輸出 ‘命令管道位置 1 的 cmdlet Invoke-WebRequest 請為以下參數提供值: Uri: ’ ?

1.原因&#xff1a; 有一個名為 Invoke-WebRequest 的 CmdLet&#xff0c;其別名為 curl。因此&#xff0c;當您執行此命令時&#xff0c;它會嘗試使用 Invoke-WebRequest&#xff0c;而不是使用 curl。 2.解決辦法 在cmd中輸入如下命令刪除這個curl別名&#xff1a; Remov…

UE5 UE循環體里怎么寫延遲

注&#xff1a;需要修改UE循環藍圖節點或者自己新建個藍圖宏庫把UE循環節點的原來代碼粘貼進去修改。 一、For Loop With Delay 二、For Each Loop With Delay 示例使用&#xff1a; 標注參考出處&#xff1a;分享UE5自制Loop with delay宏&#xff0c;在loop循環中添加執行…

IP檢測工具“ipjiance”

目錄 IP質量檢測 應用場景 對網絡安全的貢獻 對網絡管理的幫助 對用戶決策的輔助作用 IP質量檢測 檢測IP的網絡提供商&#xff1a;通過ASN&#xff08;自治系統編號&#xff09;識別IP地址所屬的網絡運營商&#xff0c;例如電信、移動、聯通等。 識別網絡類型&#xff1…

[工具]Java xml 轉 Json

[工具]Java xml 轉 Json 依賴 <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --> <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.37</version> </dependen…

vue3 傳參 傳入變量名

背景&#xff1a; 需求是&#xff1a;在vue框架中&#xff0c;接口傳參我們需要穿“變量名”&#xff0c;而不是字符串 通俗點說法是&#xff1a;在網絡接口請求的時候&#xff0c;要傳屬性名 效果展示&#xff1a; vue2核心代碼&#xff1a; this[_keyParam] vue3核心代碼&…

spring響應式編程系列:總體流程

目錄 示例 程序流程 just subscribe new LambdaMonoSubscriber ???????MonoJust.subscribe ???????new Operators.ScalarSubscription ???????onSubscribe ???????request ???????onNext 時序圖 類圖 數據發布者 MonoJust …

基于slimBOXtv 9.16 V2-晶晨S905L3A/ S905L3AB-Mod ATV-Android9.0-線刷通刷固件包

基于slimBOXtv 9.16 V2-晶晨S905L3A&#xff0f; S905L3AB-Mod ATV-Android9.0-線刷通刷固件包&#xff0c;基于SlimBOXtv 9 修改而來&#xff0c;貼近于原生ATV&#xff0c;僅支持晶晨S905L3A&#xff0f; S905L3AB芯片刷機。 適用型號&#xff1a;M401A、CM311-1a、CM311-1s…

使用droidrun庫實現AI控制安卓手機

使用droidrun庫實現AI控制安卓手機 介紹 DroidRun 是一個框架&#xff0c;通過LLM代理控制 Android 設備。它允許您使用自然語言命令自動化 Android 設備交互。 安裝環境 安裝源碼依賴 git clone https://github.com/droidrun/droidrun.git cd droidrun conda create --nam…

知識庫建設全流程指南(AI時代優化版)

知識庫建設全流程指南&#xff08;AI時代優化版&#xff09; ??一、知識庫建設的戰略定位?? ??核心價值錨點?? ??AI時代基建??&#xff1a;知識庫是GEO優化的核心載體&#xff0c;決定內容被AI引用的概率權重??動態護城河??&#xff1a;結構化知識體系可抵御算…

2025年03月中國電子學會青少年軟件編程(Python)等級考試試卷(五級)真題

青少年軟件編程&#xff08;Python&#xff09;等級考試試卷&#xff08;五級&#xff09; 分數&#xff1a;100 題數&#xff1a;38 答案解析&#xff1a;https://blog.csdn.net/qq_33897084/article/details/147341437 一、單選題(共25題&#xff0c;共50分) 1. 以下哪個選…

基于RRT的優化器:一種基于快速探索隨機樹算法的新型元啟發式算法

受機器人路徑規劃中常用的快速探索隨機樹&#xff08;RRT&#xff09;算法的搜索機制的啟發&#xff0c;我們提出了一種新穎的元啟發式算法&#xff0c;稱為基于RRT的優化器&#xff08;RRTO&#xff09;。這是首次將RRT算法的概念與元啟發式算法相結合。RRTO的關鍵創新是其三種…

進階篇|CAN FD 與性能優化

引言 1. CAN vs. CAN FD 對比 2. CAN FD 幀結構詳解

【隨身WiFi】隨身WiFi Debian系統優化教程

0.操作前必看 本教程基于Debian系統進行優化&#xff0c;有些操作對隨身WiFi來說可能會帶來負優化&#xff0c;根據需要選擇。 所有操作需要在root用戶環境下運行&#xff0c;否則都要加sudo 隨身wifi Debian系統&#xff0c;可以去某安的隨聲WiFi模塊自行搜索刷機 點贊&am…

【Pandas】pandas DataFrame where

Pandas2.2 DataFrame Indexing, iteration 方法描述DataFrame.head([n])用于返回 DataFrame 的前幾行DataFrame.at快速訪問和修改 DataFrame 中單個值的方法DataFrame.iat快速訪問和修改 DataFrame 中單個值的方法DataFrame.loc用于基于標簽&#xff08;行標簽和列標簽&#…