vue3部署 及 生成多页面(假)

编辑 / vue / 发布于2025-12-11 / 更新于2025-12-11 / 阅读 3

注意问题

  • 插件是 vite-ssg 而不是老版本的vite-plugin-ssg

  • usehead 要用 @unhead/vue 不要用老版本的 @vueuse/head

  • 别忘了配置服务器相关内容(如caddy/nginx)

VUE 页面与SEO问题

Vue 默认构建的是单页应用 (SPA),依赖 JS 动态渲染来实现无刷新跳转,体验流畅。

但这会导致 SEO 问题,因为爬虫难以抓取动态生成的 Title 和 Meta。

因此,我们需要将页面预渲染为独立的静态 HTML 文件,确保搜索引擎能直接读取内容。

解决方法: vite-ssg多页面生成SSG and 水合(hydration)

应该的工作流程是:

  1. 加载(静态文件) 用户访问 /abc,服务器隐式返回 abc.html 的文件内容。浏览器拿到后直接渲染 HTML,用户立刻看到完整的页面(标题、文字、布局),此时页面是静态的。

    SEO 可以检索

  2. JS (水合)Vue 启动后,根据 URL /abc 匹配组件,生成虚拟 DOM。它与当前页面真实的 DOM 对比,发现结构一致,便不再重新渲染,而是直接将事件监听器(如点击事件)挂载到现有 DOM 上。页面从“静态”变为“动态”。

  3. 后续跳转(SPA 模式) 水合完成后,Vue Router 全权接管页面。当用户点击内部链接时,Router 拦截浏览器默认跳转,使用 History API 修改地址栏 URL,并在客户端直接替换组件内容(销毁旧组件,渲染新组件)。后续操作不再请求 HTML 文件。

其实这个 静态 HTML 文件 只是用来优化SEO和作为入口文件的,实际上访问是还是SPA。

SSG 配置

安装 vite-ssg vue-router @unhead/vue

npm i -D vite-ssg vue-router @unhead/vue

main 文件

// src/main.ts
import { ViteSSG } from 'vite-ssg'
import App from './App.vue'

// `export const createApp` is required instead of the original `createApp(App).mount('#app')`
export const createApp = ViteSSG(
  // the root component
  App,
  // vue-router options
  { routes },
  // function to have custom setups
  ({ app, router, routes, isClient, initialState }) => {
    // install plugins etc.
  },
)

页面配置 head

<template>
</template>

<script setup>
import { useHead } from '@unhead/vue'

useHead({
  title: 'Website Title',
  meta: [
    {
      name: 'description',
      content: 'Website description',
    },
  ],
})
</script>

路由文件

export default [
  {
    path: '/',
    component: BaseTemplate,
    children: [
      { path: '/', name: 'home', component: HomePage },
      ...Routes,
    ],
  },
]

package 配置

添加红色行

{
  "name": "xxx",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build ",
    "preview": "vite preview",
    "buildssg": "vite-ssg build "
  },
  "dependencies": {
    "@vueuse/head": "^2.0.0",
    "axios": "^1.13.2",
    "compressorjs": "^1.2.1",
    "echarts": "^6.0.0",
    "file-saver": "^2.0.5",
    "jszip": "^3.10.1",
    "sitemap": "^9.0.0",
    "vue": "^3.5.24",
    "vue-echarts": "^8.0.1"
  },
  "devDependencies": {
    "@tailwindcss/vite": "^4.1.17",
    "@unhead/vue": "^2.0.19",
    "@vitejs/plugin-vue": "^6.0.1",
    "daisyui": "^5.5.5",
    "tailwindcss": "^4.1.17",
    "vite": "^7.2.4",
    "vite-plugin-sitemap": "^0.8.2",
    "vite-ssg": "^28.2.2",
    "vue-router": "^4.6.3"
  }

Caddy 配置

xxx.com {
    # 1. 设置网站根目录
    root * /var/www/site
    encode gzip zstd

    # 3. 核心逻辑:文件查找顺序
    # 当用户访问 /abc 时,Caddy 会按顺序尝试查找文件:
    # A. {path}: 是否存在名为 abc 的文件?(通常用于图片、JS资源)
    # B. {path}.html: 是否存在 abc.html?(隐式发送内容,URL 不变)
    # C. {path}/index.html: 是否存在 abc/index.html?(如果改用了目录结构方案)
    # D. /index.html: 都没找到?发送首页 (兜底,交给 Vue Router 处理 404 或动态路由)
    try_files {path} {path}.html {path}/index.html /index.html

    # 4. 开启静态文件服务
    file_server
}

web