项目简介
本项目是一个基于Vue 3和Vite的服务器端渲染(SSR)应用,借助Vue 3的强大功能与Vite的快速构建能力,结合Koa2作为服务器端框架,打造出首屏加载速度快、SEO友好的Web应用开发框架。
项目的主要特性和功能
- 服务器端渲染(SSR):实现首屏快速加载,利于SEO优化。
- Vue 3:运用Composition API和响应式系统,开发更灵活高效。
- Vite:利用其快速开发和构建能力,提升开发效率。
- Koa2:作为服务器端框架,提供轻量级、高性能的服务器环境。
- Pinia:集成该状态管理工具,提供简单高效的状态管理方案。
- Vue Router:实现前端路由管理。
- TypeScript:进行类型检查,提升代码质量和可维护性。
安装使用步骤
1. 初始化项目
使用pnpm创建并初始化项目:
shell
pnpm create vite koa2-ssr-vue3-ts-pinia -- --template vue-ts
2. 修改客户端入口
修改~/src/main.ts
文件,创建SSR应用实例:
```ts
import { createSSRApp } from "vue";
import App from "./App.vue";
export const createApp = () => {
const app = createSSRApp(App);
return { app };
}
新建`~/src/entry-client.ts`文件,挂载Vue应用:
ts
import { createApp } from "./main"
const { app } = createApp();
app.mount("#app");
修改`~/index.html`文件,设置入口:
html
```
3. 创建开发服务器
安装Koa2及相关中间件:
shell
pnpm i koa --save && pnpm i @types/koa --save-dev
pnpm i koa-connect --save
新建~/server.js
文件,配置Koa2服务器:
```js
const Koa = require('koa');
const fs = require('fs');
const path = require('path');
(async () => { const app = new Koa();
const template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8');
app.use(async (ctx) => {
let vueTemplate = '<h1 style="text-align:center;">现在假装这是一个vue模板</h1>';
let html = template.replace('<!--app-html-->', vueTemplate);
ctx.body = html;
});
app.listen(9000, () => {
console.log('server is listening in 9000');
});
})(); ```
4. 新增服务端入口
安装@vue/server-renderer
:
shell
pnpm i @vue/server-renderer --save
新建~/src/entry-server.ts
文件,配置服务端渲染:
```ts
import { createApp } from './main';
import { renderToString } from '@vue/server-renderer';
export const render = async () => { const { app } = createApp(); const renderCtx: {modules?: string[]} = {} let renderedHtml = await renderToString(app, renderCtx) return { renderedHtml }; } ```
5. 注入Vite
修改~/server.js
文件,集成Vite:
```js
const fs = require('fs')
const path = require('path')
const Koa = require('koa')
const koaConnect = require('koa-connect')
const vite = require('vite')
;(async () => { const app = new Koa(); const viteServer = await vite.createServer({ root: process.cwd(), logLevel: 'error', server: { middlewareMode: true } }) app.use(koaConnect(viteServer.middlewares))
app.use(async ctx => {
try {
let template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8');
template = await viteServer.transformIndexHtml(ctx.path, template)
const { render } = await viteServer.ssrLoadModule('/src/entry-server.ts')
const { renderedHtml } = await render(ctx, {})
const html = template.replace('<!--app-html-->', renderedHtml)
ctx.type = 'text/html'
ctx.body = html
} catch (e) {
viteServer && viteServer.ssrFixStacktrace(e)
console.log(e.stack)
ctx.throw(500, e.stack)
}
})
app.listen(9000, () => {
console.log('server is listening in 9000');
});
})() ```
6. 添加开发环境
修改package.json
,添加构建和运行脚本:
json
{
"scripts": {
"dev": "node server-dev.js",
"server": "node server-prod.js",
"build": "pnpm build:client && pnpm build:server",
"build:client": "vite build --outDir dist/client",
"build:server": "vite build --ssr src/entry-server.js --outDir dist/server"
}
}
7. 预加载
在package.json
中添加预加载指令:
json
{
"scripts": {
"build:client": "vite build --ssrManifest --outDir dist/client"
}
}
在entry-server.ts
中添加解析预加载链接的方法:
```ts
function renderPreloadLinks(modules: undefined | string[], manifest: Record
function renderPreloadLink(file: string): string {
if (file.endsWith('.js')) {
return <link rel="modulepreload" crossorigin href="${file}">
;
} else if (file.endsWith('.css')) {
return <link rel="stylesheet" href="${file}">
;
} else {
return '';
}
}
```
8. 集成Vue Router
安装Vue Router:
shell
pnpm i vue-router --save
配置路由文件src/router/index.ts
:
```ts
import { createRouter, createMemoryHistory, createWebHistory, Router } from 'vue-router';
export const createRouter = (type: 'client' | 'server'): Router => createRouter({ history: type === 'client' ? createWebHistory() : createMemoryHistory(), routes: [ { path: '/', name: 'index', component: () => import('@/pages/index.vue') }, ] }); ```
9. 集成Pinia
安装Pinia:
shell
pnpm i pinia --save
配置Pinia状态管理:
```ts
import { createPinia } from 'pinia';
import useUserStore from './user';
export default () => { const pinia = createPinia(); useUserStore(pinia); return pinia; }; ```
10. 运行项目
在开发环境运行:
shell
pnpm run dev
在生产环境运行:
shell
pnpm run build
pnpm run server
下载地址
点击下载 【提取码: 4003】【解压密码: www.makuang.net】