Vue3

本教程将帮助你从零开始搭建一个基于 Esmx 的 Vue3 SSR 应用。我们将通过一个完整的示例来展示如何使用 Esmx 框架创建服务端渲染应用。

项目结构

首先,让我们了解项目的基本结构:

1.
2├── package.json         # 项目配置文件,定义依赖和脚本命令
3├── tsconfig.json        # TypeScript 配置文件,设置编译选项
4└── src                  # 源代码目录
5    ├── app.vue          # 主应用组件,定义页面结构和交互逻辑
6    ├── create-app.ts    # Vue 实例创建工厂,负责初始化应用
7    ├── entry.client.ts  # 客户端入口文件,处理浏览器端渲染
8    ├── entry.node.ts    # Node.js 服务器入口文件,负责开发环境配置和服务器启动
9    └── entry.server.ts  # 服务端入口文件,处理 SSR 渲染逻辑

项目配置

package.json

创建 package.json 文件,配置项目依赖和脚本:

package.json
1{
2  "name": "ssr-demo-vue3",
3  "version": "1.0.0",
4  "type": "module",
5  "private": true,
6  "scripts": {
7    "dev": "esmx dev",
8    "build": "npm run build:dts && npm run build:ssr",
9    "build:ssr": "esmx build",
10    "preview": "esmx preview",
11    "start": "NODE_ENV=production node dist/index.mjs",
12    "build:dts": "vue-tsc --declaration --emitDeclarationOnly --outDir dist/src"
13  },
14  "dependencies": {
15    "@esmx/core": "*"
16  },
17  "devDependencies": {
18    "@esmx/rspack-vue": "*",
19    "@types/node": "22.8.6",
20    "@vue/server-renderer": "^3.5.13",
21    "typescript": "^5.7.3",
22    "vue": "^3.5.13",
23    "vue-tsc": "^2.1.6"
24  }
25}

创建完 package.json 文件后,需要安装项目依赖。你可以使用以下任一命令来安装:

1pnpm install
2# 或
3yarn install
4# 或
5npm install

这将安装所有必需的依赖包,包括 Vue3、TypeScript 和 SSR 相关的依赖。

tsconfig.json

创建 tsconfig.json 文件,配置 TypeScript 编译选项:

tsconfig.json
1{
2    "compilerOptions": {
3        "module": "ESNext",
4        "moduleResolution": "node",
5        "isolatedModules": true,
6        "resolveJsonModule": true,
7        
8        "target": "ESNext",
9        "lib": ["ESNext", "DOM"],
10        
11        "strict": true,
12        "skipLibCheck": true,
13        "types": ["@types/node"],
14        
15        "experimentalDecorators": true,
16        "allowSyntheticDefaultImports": true,
17        
18        "baseUrl": ".",
19        "paths": {
20            "ssr-demo-vue3/src/*": ["./src/*"],
21            "ssr-demo-vue3/*": ["./*"]
22        }
23    },
24    "include": ["src"],
25    "exclude": ["dist", "node_modules"]
26}

源码结构

app.vue

创建主应用组件 src/app.vue,使用 Vue3 的组合式 API:

src/app.vue
1<template>
2    <div>
3        <h1><a href="https://www.esmnext.com/guide/frameworks/vue3.html" target="_blank">Esmx 快速开始</a></h1>
4        <time :datetime="time">{{ time }}</time>
5    </div>
6</template>
7
8<script setup lang="ts">
9/**
10 * @file 示例组件
11 * @description 展示一个带有自动更新时间的页面标题,用于演示 Esmx 框架的基本功能
12 */
13
14import { onMounted, onUnmounted, ref } from 'vue';
15
16// 当前时间,每秒更新一次
17const time = ref(new Date().toISOString());
18let timer: NodeJS.Timeout;
19
20onMounted(() => {
21    timer = setInterval(() => {
22        time.value = new Date().toISOString();
23    }, 1000);
24});
25
26onUnmounted(() => {
27    clearInterval(timer);
28});
29</script>

create-app.ts

创建 src/create-app.ts 文件,负责创建 Vue 应用实例:

src/create-app.ts
1/**
2 * @file Vue 实例创建
3 * @description 负责创建和配置 Vue 应用实例
4 */
5
6import { createSSRApp } from 'vue';
7import App from './app.vue';
8
9export function createApp() {
10    const app = createSSRApp(App);
11    return {
12        app
13    };
14}

entry.client.ts

创建客户端入口文件 src/entry.client.ts

src/entry.client.ts
1/**
2 * @file 客户端入口文件
3 * @description 负责客户端交互逻辑和动态更新
4 */
5
6import { createApp } from './create-app';
7
8// 创建 Vue 实例
9const { app } = createApp();
10
11// 挂载 Vue 实例
12app.mount('#app');

entry.node.ts

创建 entry.node.ts 文件,配置开发环境和服务器启动:

src/entry.node.ts
1/**
2 * @file Node.js 服务器入口文件
3 * @description 负责开发环境配置和服务器启动,提供 SSR 运行时环境
4 */
5
6import http from 'node:http';
7import type { EsmxOptions } from '@esmx/core';
8
9export default {
10    /**
11     * 配置开发环境的应用创建器
12     * @description 创建并配置 Rspack 应用实例,用于开发环境的构建和热更新
13     * @param esmx Esmx 框架实例,提供核心功能和配置接口
14     * @returns 返回配置好的 Rspack 应用实例,支持 HMR 和实时预览
15     */
16    async devApp(esmx) {
17        return import('@esmx/rspack-vue').then((m) =>
18            m.createRspackVue3App(esmx, {
19                config(context) {
20                    // 在此处自定义 Rspack 编译配置
21                }
22            })
23        );
24    },
25
26    /**
27     * 配置并启动 HTTP 服务器
28     * @description 创建 HTTP 服务器实例,集成 Esmx 中间件,处理 SSR 请求
29     * @param esmx Esmx 框架实例,提供中间件和渲染功能
30     */
31    async server(esmx) {
32        const server = http.createServer((req, res) => {
33            // 使用 Esmx 中间件处理请求
34            esmx.middleware(req, res, async () => {
35                // 执行服务端渲染
36                const rc = await esmx.render({
37                    params: { url: req.url }
38                });
39                res.end(rc.html);
40            });
41        });
42
43        server.listen(3000, () => {
44            console.log('服务启动: http://localhost:3000');
45        });
46    }
47} satisfies EsmxOptions;

这个文件是开发环境配置和服务器启动的入口文件,主要包含两个核心功能:

  1. devApp 函数:负责创建和配置开发环境的 Rspack 应用实例,支持热更新和实时预览功能。这里使用 createRspackVue3App 来创建专门用于 Vue3 的 Rspack 应用实例。
  2. server 函数:负责创建和配置 HTTP 服务器,集成 Esmx 中间件处理 SSR 请求。

entry.server.ts

创建服务端渲染入口文件 src/entry.server.ts

src/entry.server.ts
1/**
2 * @file 服务端渲染入口文件
3 * @description 负责服务端渲染流程、HTML 生成和资源注入
4 */
5
6import type { RenderContext } from '@esmx/core';
7import { renderToString } from '@vue/server-renderer';
8import { createApp } from './create-app';
9
10export default async (rc: RenderContext) => {
11    // 创建 Vue 应用实例
12    const { app } = createApp();
13
14    // 使用 Vue 的 renderToString 生成页面内容
15    const html = await renderToString(app, {
16        importMetaSet: rc.importMetaSet
17    });
18
19    // 提交依赖收集,确保所有必要资源都被加载
20    await rc.commit();
21
22    // 生成完整的 HTML 结构
23    rc.html = `<!DOCTYPE html>
24<html lang="zh-CN">
25<head>
26    ${rc.preload()}
27    <title>Esmx 快速开始</title>
28    ${rc.css()}
29</head>
30<body>
31    <div id="app">${html}</div>
32    ${rc.importmap()}
33    ${rc.moduleEntry()}
34    ${rc.modulePreload()}
35</body>
36</html>
37`;
38};

运行项目

完成上述文件配置后,你可以使用以下命令来运行项目:

  1. 开发模式:
1npm run dev
  1. 构建项目:
1npm run build
  1. 生产环境运行:
1npm run start

现在,你已经成功创建了一个基于 Esmx 的 Vue3 SSR 应用!访问 http://localhost:3000 即可看到效果。