Vue3+TypeScript+Vite服務(wù)端渲染項(xiàng)目的實(shí)現(xiàn)
項(xiàng)目簡介
這是一個(gè)基于 Vue 3、TypeScript 和 Vite 構(gòu)建的現(xiàn)代化前端項(xiàng)目,同時(shí)支持服務(wù)端渲染 (SSR) 和客戶端渲染 (CSR) 兩種模式。項(xiàng)目展示了如何在 Vue 3 應(yīng)用中實(shí)現(xiàn)完整的 SSR 功能,包括數(shù)據(jù)預(yù)取、元信息管理和服務(wù)端渲染管道。
技術(shù)棧
- 前端框架: Vue 3 (Composition API)
- 編程語言: TypeScript
- 構(gòu)建工具: Vite 7.x
- 路由管理: Vue Router 4
- 運(yùn)行時(shí)環(huán)境: Bun
- 服務(wù)端渲染: Vue SSR
項(xiàng)目結(jié)構(gòu)
h5/ ├── src/ # 源代碼目錄 │ ├── assets/ # 靜態(tài)資源文件 │ ├── page/ # 頁面組件 │ ├── use/ # 自定義 hooks │ ├── app.ts # 應(yīng)用創(chuàng)建邏輯 │ ├── main.ts # 客戶端入口文件 │ └── server.ts # SSR 渲染邏輯 ├── server.ts # 服務(wù)端入口文件 (Bun 服務(wù)器) ├── vite.config.ts # Vite 配置 ├── package.json # 項(xiàng)目配置和依賴 └── index.html # HTML 入口文件
核心功能模塊
1. 應(yīng)用創(chuàng)建與路由管理 (app.ts)
該模塊負(fù)責(zé)創(chuàng)建 Vue 應(yīng)用實(shí)例并配置路由系統(tǒng),同時(shí)支持 SSR 和 CSR 兩種模式。
主要功能:
- 創(chuàng)建支持 SSR 的 Vue 應(yīng)用實(shí)例
- 配置路由規(guī)則和組件懶加載
- 根據(jù)環(huán)境選擇合適的路由歷史模式
// src/app.ts
import { createSSRApp } from 'vue'
import App from './App.vue'
import { createRouter, createMemoryHistory, createWebHistory } from 'vue-router'
export function createApp(ssr: boolean = false) {
const app = createSSRApp(App)
const routes = [
{ path: '/', component: () => import('./page/home.vue'), meta: { title: 'home' } },
{ path: '/about', component: () => import('./page/about.vue'), meta: { title: 'about' } },
]
const router = createRouter({
history: ssr ? createMemoryHistory() : createWebHistory(),
routes,
})
app.use(router)
return { app, router }
}
2. 頁面元信息管理 (use/head.ts)
自定義 hook 用于管理頁面標(biāo)題、關(guān)鍵詞和描述等元信息,同時(shí)支持 SSR 和 CSR 環(huán)境。
主要功能:
- 統(tǒng)一管理頁面元數(shù)據(jù)
- 在客戶端環(huán)境中自動更新 DOM
- 支持 SSR 上下文傳遞元數(shù)據(jù)
// src/use/head.ts
import { ref, type Ref, onMounted } from 'vue'
type HeadType = {
title: string,
keyword: string,
description: string
}
export const head: Ref<HeadType> = ref({
title: '',
keyword: '',
description: ''
})
export function useHead(init: HeadType) {
// 在服務(wù)器端和客戶端都設(shè)置head數(shù)據(jù)
head.value = init
// 只在客戶端環(huán)境中操作DOM
onMounted(() => {
try {
if (document.title !== init.title) {
document.title = init.title
document.head.querySelector('meta[name="keyword"]')?.setAttribute('content', init.keyword)
document.head.querySelector('meta[name="description"]')?.setAttribute('content', init.description)
}
} catch (e) {
console.log(e)
}
})
}
3. 服務(wù)端渲染實(shí)現(xiàn) (src/server.ts & server.ts)
項(xiàng)目實(shí)現(xiàn)了完整的 SSR 渲染流程,包括路由預(yù)解析、組件渲染和 HTML 拼接。
主要功能:
- 創(chuàng)建 SSR 模式的應(yīng)用實(shí)例
- 處理 URL 請求和路由跳轉(zhuǎn)
- 預(yù)加載路由組件
- 渲染應(yīng)用為 HTML 字符串
- 傳遞元數(shù)據(jù)到客戶端
// src/server.ts
import { renderToString } from '@vue/server-renderer'
import { createApp } from './app'
import { head } from './use/head'
export async function render(url: string) {
const { app, router } = createApp(true)
const ctx = { 'head': head.value }
router.push(url)
await router.isReady()
const html = await renderToString(app, ctx)
return { html, ctx }
}
// server.ts (Bun服務(wù)器)
import { serve, file } from 'bun'
serve({
port: 3000,
async fetch(req) {
let url = new URL(req.url)
// 處理靜態(tài)資源
if (url.pathname.startsWith('/assets')) {
// 靜態(tài)資源處理邏輯...
}
// 渲染Vue應(yīng)用
const render = (await import('./dist/server/server.js')).render
const html = await file('./dist/client/index.html').text()
const rendered = await render(url.pathname)
return new Response(
html
.replace('<!--app-html-->', rendered.html)
.replace('<!--app-head-html-->', rendered.ctx.head.title)
.replace('<!--app-head-keyword-->', rendered.ctx.head.keyword)
.replace('<!--app-head-description-->', rendered.ctx.head.description),
{
headers: { 'Content-Type': 'text/html' }
}
)
}
})
4. 頁面組件實(shí)現(xiàn)
項(xiàng)目包含兩個(gè)主要頁面組件:首頁和關(guān)于頁面,均實(shí)現(xiàn)了 SSR 環(huán)境下的數(shù)據(jù)預(yù)取。
核心特性:
- 使用
onServerPrefetch確保在 SSR 環(huán)境中預(yù)取數(shù)據(jù) - 集中管理頁面元信息設(shè)置
- 組件懶加載優(yōu)化性能
// 頁面組件示例 (home.vue)
<script lang="ts" setup>
import { onServerPrefetch } from 'vue'
import { useHead } from '../use/head'
const init = () => {
useHead({
title: '關(guān)于我們-ssr,全??蚣?,
keyword: '關(guān)于我們,ssr,全??蚣?,
description: '關(guān)于我們-ssr,全??蚣?
})
}
// 在客戶端和服務(wù)端都執(zhí)行
init()
// 僅在服務(wù)端渲染時(shí)執(zhí)行,確保元信息正確設(shè)置
onServerPrefetch(() => {
init()
})
</script>
構(gòu)建與運(yùn)行腳本
項(xiàng)目提供了以下 npm 腳本用于開發(fā)和構(gòu)建:
# 開發(fā)模式(CSR) npm run dev # 服務(wù)端渲染構(gòu)建和運(yùn)行 npm run ssr # 構(gòu)建生產(chǎn)版本 npm run build # 預(yù)覽生產(chǎn)構(gòu)建結(jié)果 npm run preview
Vite 配置
項(xiàng)目的 Vite 配置支持 SSR 模式,并設(shè)置了一些優(yōu)化選項(xiàng):
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
ssr: {
noExternal: ['vue'] // 確保 Vue 在 SSR 構(gòu)建中被正確處理
},
build: {
assetsInlineLimit: 0 // 禁用資源內(nèi)聯(lián)
}
})
客戶端入口 (main.ts)
客戶端入口文件負(fù)責(zé)創(chuàng)建 Vue 應(yīng)用實(shí)例并掛載到 DOM 上:
// src/main.ts
import { createApp } from './app'
const { app } = createApp()
app.mount('#app')
開發(fā)注意事項(xiàng)
SSR 環(huán)境下的數(shù)據(jù)預(yù)取
- 使用
onServerPrefetch鉤子確保在服務(wù)器端正確預(yù)取數(shù)據(jù) - 確保組件中的 DOM 操作僅在客戶端執(zhí)行
- 使用
元信息管理
- 使用
useHeadhook 統(tǒng)一管理頁面元信息 - 服務(wù)端會將元信息傳遞給客戶端,確保 SEO 友好
- 使用
注意事項(xiàng)(發(fā)現(xiàn)的問題)
home.vue和about.vue中存在標(biāo)題設(shè)置錯(cuò)誤:首頁組件設(shè)置了"關(guān)于我們"的標(biāo)題,而關(guān)于頁面設(shè)置了"首頁"的標(biāo)題- 需要修正這兩個(gè)文件中的元信息設(shè)置,確保標(biāo)題與頁面內(nèi)容一致
技術(shù)亮點(diǎn)
完整的 SSR 實(shí)現(xiàn):項(xiàng)目展示了 Vue 3 中完整的服務(wù)端渲染實(shí)現(xiàn),包括路由預(yù)解析、數(shù)據(jù)預(yù)取和 HTML 渲染
統(tǒng)一的元信息管理:通過自定義 hook 實(shí)現(xiàn)了 SSR 和 CSR 環(huán)境下的元信息統(tǒng)一管理
基于 Bun 的服務(wù)端:使用現(xiàn)代的 Bun 運(yùn)行時(shí)作為服務(wù)端環(huán)境,提升性能
組件懶加載:路由組件使用動態(tài)導(dǎo)入實(shí)現(xiàn)懶加載,優(yōu)化初始加載性能
部署說明
安裝依賴
bun install
構(gòu)建項(xiàng)目
bun run build
服務(wù)端渲染部署
bun run ssr
訪問應(yīng)用 打開瀏覽器訪問 http://localhost:3000
到此這篇關(guān)于Vue 3 + TypeScript + Vite 服務(wù)端渲染項(xiàng)目的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Vue TypeScript Vite 服務(wù)端渲染內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue3 Element Plus el-form表單組件示例詳解
這篇文章主要介紹了Vue3 Element Plus el-form表單組件,Element Plus 是 ElementUI 的升級版,提供了更多的表單控件和功能,同時(shí)還改進(jìn)了一些細(xì)節(jié)和樣式,本文結(jié)合示例代碼給大家詳細(xì)講解,需要的朋友可以參考下2023-04-04
element-vue實(shí)現(xiàn)網(wǎng)頁鎖屏功能(示例代碼)
這篇文章主要介紹了element-vue實(shí)現(xiàn)網(wǎng)頁鎖屏功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-11-11
Vue2.0+ElementUI+PageHelper實(shí)現(xiàn)的表格分頁功能
ElementUI也是一套很不錯(cuò)的組件庫,對于我們經(jīng)常用到的表格、表單、時(shí)間日期選擇器等常用組件都有著很好的封裝和接口。這篇文章主要介紹了Vue2.0+ElementUI+PageHelper實(shí)現(xiàn)的表格分頁,需要的朋友可以參考下2021-10-10
關(guān)于vue2強(qiáng)制刷新,解決頁面不會重新渲染的問題
今天小編就為大家分享一篇關(guān)于vue2強(qiáng)制刷新,解決頁面不會重新渲染的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10
vue+element_ui上傳文件,并傳遞額外參數(shù)操作
這篇文章主要介紹了vue+element_ui上傳文件,并傳遞額外參數(shù)操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
Vue 自定義指令實(shí)現(xiàn)一鍵 Copy功能
指令 (Directives) 是帶有 v- 前綴的特殊特性。這篇文章主要介紹了Vue 自定義指令實(shí)現(xiàn)一鍵 Copy的功能,需要的朋友可以參考下2019-09-09
Vue中對iframe實(shí)現(xiàn)keep alive無刷新的方法
這篇文章主要介紹了Vue中對iframe實(shí)現(xiàn)keep alive無刷新的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
webpack+vue+express(hot)熱啟動調(diào)試簡單配置方法
今天小編就為大家分享一篇webpack+vue + express (hot) 熱啟動調(diào)試簡單配置方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09

