Hello World

最简单的 VextJS 项目,帮助你理解框架的基本结构和工作方式。

完整项目结构

hello-world/
  ├── src/
  │   ├── config/
  │   │   └── default.ts
  │   ├── routes/
  │   │   └── index.ts
  │   └── index.ts
  ├── package.json
  └── tsconfig.json

1. 初始化项目

使用 vext create 脚手架快速创建:

npx vextjs create hello-world
cd hello-world
pnpm install

或手动创建:

mkdir hello-world && cd hello-world
pnpm init
pnpm add vextjs
pnpm add -D typescript @types/node

2. 配置文件

package.json

{
  "name": "hello-world",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vext dev",
    "build": "vext build",
    "start": "vext start"
  },
  "dependencies": {
    "vextjs": "latest"
  },
  "devDependencies": {
    "typescript": "^5.7.0",
    "@types/node": "^22.0.0"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "dist",
    "rootDir": "src",
    "declaration": true
  },
  "include": ["src"]
}

3. 配置

// src/config/default.ts
export default {
  port: 3000,
  adapter: 'native',
  logger: {
    level: 'debug',
    pretty: true,
  },
  cors: {
    enabled: true,
    origins: ['*'],
  },
};
Tip

adapter: 'native' 使用内置的 Native Adapter(基于 http.createServer + find-my-way),零外部框架依赖,性能最高。也可以切换为 'hono''fastify''express''koa'业务代码无需任何改动

4. 路由

// src/routes/index.ts
import { defineRoutes } from 'vextjs';

export default defineRoutes((app) => {
  // GET / → 问候接口
  app.get('/', {
    docs: {
      summary: '问候接口',
      tags: ['基础'],
    },
  }, async (_req, res) => {
    res.json({ message: 'Hello VextJS! 🚀' });
  });

  // GET /health → 健康检查
  app.get('/health', async (_req, res) => {
    res.json({
      status: 'ok',
      uptime: process.uptime(),
      timestamp: new Date().toISOString(),
    });
  });

  // GET /echo → 回显查询参数
  app.get('/echo', {
    validate: {
      query: {
        message: 'string?',
      },
    },
    docs: {
      summary: '回显接口',
      description: '将查询参数中的 message 原样返回',
    },
  }, async (req, res) => {
    const { message } = req.valid('query');
    res.json({
      echo: message ?? 'no message provided',
      method: req.method,
      path: req.path,
      requestId: req.requestId,
      ip: req.ip,
    });
  });

  // POST /greet → 带参数校验的问候
  app.post('/greet', {
    validate: {
      body: {
        name: 'string:1-50',
        language: 'enum:zh,en,ja?',
      },
    },
    docs: {
      summary: '个性化问候',
      description: '根据姓名和语言返回问候语',
      responses: {
        200: {
          description: '问候成功',
          example: {
            greeting: '你好, Alice!',
            language: 'zh',
          },
        },
      },
    },
  }, async (req, res) => {
    const { name, language = 'zh' } = req.valid('body');

    const greetings: Record<string, string> = {
      zh: `你好, ${name}!`,
      en: `Hello, ${name}!`,
      ja: `こんにちは, ${name}!`,
    };

    res.json({
      greeting: greetings[language],
      language,
    });
  });
});

5. 入口文件

// src/index.ts
import { bootstrap } from 'vextjs';

bootstrap().catch((err) => {
  console.error('启动失败:', err);
  process.exit(1);
});

6. 运行

开发模式

pnpm dev

开发模式特性:

  • 文件修改自动热重载(三层策略:路由/服务/配置智能刷新)
  • 美化日志输出(彩色格式)
  • 自动启用 OpenAPI 文档(访问 http://localhost:3000/docs

生产模式

pnpm build
pnpm start

7. 验证

启动后可使用 curl 或浏览器验证:

# 问候接口
curl http://localhost:3000/
# → {"code":0,"data":{"message":"Hello VextJS! 🚀"},"requestId":"..."}

# 健康检查
curl http://localhost:3000/health
# → {"code":0,"data":{"status":"ok","uptime":12.34,"timestamp":"..."},"requestId":"..."}

# 回显接口
curl "http://localhost:3000/echo?message=hello"
# → {"code":0,"data":{"echo":"hello","method":"GET","path":"/echo",...},"requestId":"..."}

# 个性化问候
curl -X POST http://localhost:3000/greet \
  -H "Content-Type: application/json" \
  -d '{"name":"Alice","language":"en"}'
# → {"code":0,"data":{"greeting":"Hello, Alice!","language":"en"},"requestId":"..."}

# 参数校验测试(name 为空触发 400)
curl -X POST http://localhost:3000/greet \
  -H "Content-Type: application/json" \
  -d '{"name":""}'
# → {"code":-1,"message":"Validation failed","errors":[...],"requestId":"..."}

8. 响应格式说明

VextJS 默认启用出口包装config.response.wrap: true),所有 res.json() 的响应会自动包装为统一格式:

成功响应

{
  "code": 0,
  "data": { "message": "Hello VextJS! 🚀" },
  "requestId": "550e8400-e29b-41d4-a716-446655440000"
}

错误响应

{
  "code": -1,
  "message": "Validation failed",
  "errors": [
    { "field": "name", "message": "length must be between 1 and 50" }
  ],
  "requestId": "550e8400-e29b-41d4-a716-446655440000"
}

如果不需要包装(如微服务间通信),可在配置中禁用:

// src/config/default.ts
export default {
  response: {
    wrap: false,
  },
};

关键概念回顾

概念说明
defineRoutes路由定义函数,在回调中注册路由
bootstrap框架启动函数,编排完整的初始化流程
validate声明式参数校验(schema-dsl DSL 语法)
req.valid()获取校验并类型转换后的数据
res.json()返回 JSON 响应(自动出口包装)
docsOpenAPI 文档配置,自动生成 Scalar API 文档
出口包装统一响应格式 { code, data, requestId }

下一步