# vite-ssr **Repository Path**: projectleo/vite-ssr ## Basic Information - **Project Name**: vite-ssr - **Description**: vite已有项目修改为ssr的实践 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-05-16 - **Last Updated**: 2025-05-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 前言 将存在的vite项目修改为SSR,将此过程以本文记录。 本文代码放置在[vite-ssr](https://gitee.com/projectleo/vite-ssr.git) - 分支**csr**为纯客户端渲染版本 - 分支**ssr**为服务端渲染 # 内容涉及 - 客户端:**[Vue](https://cn.vuejs.org/)** + **[Vite](https://vitejs.cn/vite6-cn/guide/)** + **[Vue-Router](https://router.vuejs.org/zh/introduction.html)** + **[Axios](http://www.axios-js.com/zh-cn/docs/)** + **[Pinia](https://pinia.vuejs.org/)** + **[Arco Design](https://arco.design/vue/docs/start)** - 服务端:**[express](https://www.expressjs.com.cn/)** + **[compression](https://www.npmjs.com/package/compression)** + **[sriv](https://www.npmjs.com/package/sirv)** - 部署:**[nginx](https://nginx.org/ru/)** + **[pm2](https://pm2.fenxianglu.cn/)** # 正文 注:为了模拟如何将已有项目修改为ssr我会从0开始先创建一个可以使用的demo,每一步附加正确的图片 ## 1.前端项目初始化 使用 **[Vite](https://vitejs.cn/vite6-cn/guide/)** 进行项目创建,并安装上述客户端使用依赖 ```powershell npm create vite@latest ``` 进入项目目录并安装依赖 ```powershell npm i axios moment pinia pinia-plugin-persistedstate vue-router @arco-design/web-vue ``` ## 2.后端项目设置 为了符合日常开发任务,我们准备一个后端demo 1. 为项目新建一个mysql的数据库 2. 新增公司表、部门表、人员表并添加数据 代码如下 ```sql -- 创建数据库 -- 创建单位表 -- 创建部门表 -- 创建人员表 ``` 3. 新增后端项目backend 在vite-ssr同级目录下创建backend目录,项目结构如下 ```sql backend/ │ ├── app.js # 主入口文件 ├── routes/ # 路由文件夹 │ ├── company.js # 公司相关路由 │ ├── department.js # 部门相关路由 │ └── employee.js # 人员相关路由 ├── db.js # 数据库连接配置 └── package.json # 项目依赖 ``` 安装依赖body-parser和mysql2 首先配置数据库,其中数据库密码需要修改 ```javascript // db.jd const mysql = require('mysql2'); // 创建数据库连接池 const pool = mysql.createPool({ host: 'localhost', // 数据库地址 user: 'root', // 数据库用户名 password: 'your-password', // 数据库密码 database: 'vite-ssr', // 数据库名称 waitForConnections: true, connectionLimit: 10, queueLimit: 0 }); module.exports = pool.promise(); // 导出 Promise 包装的连接池 ``` 然后实现三个接口,查看backend/routes目录下的三个文件 最后由app.js启动后端项目 至此后端项目配置完成 ## 3.前端项目Demo实现 1. 创建如下目录结构 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/dddced8cba884b7bae5ac010fe3556ec.png) 2. 使用router、pinia、arco design开发三个列表界面,并实现对应的筛选功能 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/dd9b65292ccb43a39a4a6ce779d02ef2.png) ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/845b50cc0a0d47b58cb1efda26025711.png) ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/cb5fd5fb574a4b6a900546b8c6aa632e.png) csr功能已就绪,准备开始添加ssr功能 ## 4.ssr配置 1. 参照vite官网进行目录和index.html配置 SSR 应用应该有如下的源文件结构: ```javascript - index.html - server.js # ssr应用主服务 - src/ - main.js # 导出环境无关的(通用的)应用代码 - entry-client.js # 将应用挂载到一个 DOM 元素上 - entry-server.js # 使用某框架的 SSR API 渲染该应用 ``` **index.html** 将需要引用 **entry-client.js** 并包含一个占位标记供给服务端渲染时注入,由于我们会进行SEO的优化和数据传输所以该文件修改比经典结构多出部分 ```html Vite + Vue
``` 2. 主要需要关注的点是对于vue对象创建和router创建的修改,具体看main.js文件和router目录下的index.js文件对于两个对象创建的方式 3. 其次arco design在服务端无法识别有效的install方法,如果使用自动引入插件会出现es错误无法使用import引入文件,解决方案为使用组件大类的install方法 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/ead1e5c6d92f4bfcbb1a650473856b32.png) 4. 对于数据的传输使用pinia进行序列化和反序列化,ssr渲染后将数据传递到客户端。其流程为首先在main.js导出pinia,在entry-server.js文件使用`` const initialState = JSON.stringify(pinia.state.value); ``进行数据状态序列化,然后在server.js传递数据到渲染界面 ```js const html = template .replace(``, rendered.head ?? '') .replace(``, rendered.html ?? '') .replace("", ``); ``` 最后在entry-client.js文件加载客户端时恢复数据 ```js const { app, router, pinia } = createApp() // 恢复服务端传递的初始状态 if (window.__INITIAL_STATE__) { pinia.state.value = window.__INITIAL_STATE__; } ``` 5. 为何水合内容的完全匹配,一般来说服务端渲染和客户端渲染需要使用相同数据,因此首次加载时一般在客户端不再做二次接口请求处理,使用onServerPrefetch在服务端获取数据进行保存并通过上一步进行数据传递,当客户端渲染时检测到数据已存在则不会进行新数据的获取而是使用服务端的数据进行渲染,以达到完全匹配的水合 ```js onServerPrefetch(async () => { await getDataList(); }); onMounted(async () => { if (data.value.length === 0) { await getDataList(); } }); ``` # 总结 1. 如果是新项目千万不要使用该方案,麻烦且复杂,不如nuxtjs一把唆 2. 如果你的数据比较复杂不建议将数据进行服务端到客户端的传输,因为序列化和反序列化可能出错,只要返回的服务端渲染界面包含数据即可,水合不匹配影响不大 3. ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/9b9ea40213964a3e91a7bc58bd0bbd3a.png)此类错误可在server.js文件204直接屏蔽 4. [代码仓库](https://gitee.com/projectleo/vite-ssr/tree/master/)在此,期待指正、交流、提问!