npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vextjs

v0.1.4

Published

VextJS is a modern Node.js web framework with adapter architecture, plugin system, and out-of-the-box features for building high-performance RESTful APIs.

Readme

VextJS

License: MIT Node.js TypeScript

一个现代化的 Node.js Web 框架,开箱即用,专为构建高性能 RESTful API 而设计。

VextJS 提供 Adapter 架构(底层可替换)、插件系统、约定式路由、服务自动注入、参数校验、OpenAPI 文档自动生成等企业级特性,让你专注于业务逻辑。


✨ 特性

  • 🔌 Adapter 架构 — 底层 HTTP 框架可替换(默认 Native Adapter,零外部依赖),业务代码无需改动
  • 📁 约定式路由src/routes/ 下的文件自动扫描加载,文件路径即路由前缀
  • 🧩 插件系统 — 拓扑排序、依赖声明、生命周期钩子,轻松扩展框架能力
  • 💉 服务自动注入src/services/ 下的 class 自动实例化并挂载到 app.services
  • 🛡️ 参数校验 — 集成 schema-dsl,声明式校验 + i18n 错误消息
  • 📖 OpenAPI 文档 — 路由元信息自动收集,生成 OpenAPI 3.1 JSON
  • 🔥 开发模式热重载 — 三层重载策略(Soft Reload + Cold Restart),毫秒级反馈
  • 🏗️ 内置中间件 — requestId、CORS、bodyParser、rateLimit、accessLog、responseWrapper 开箱即用
  • 🌐 i18n 支持src/locales/ 语言包自动加载,校验错误消息多语言
  • 🧪 测试工具 — 内置 createTestApp,无需启动 HTTP 服务器即可测试路由
  • ⚡ TypeScript 原生 — 完整类型定义,极致的 IDE 补全体验
  • 📦 零配置启动 — 合理的默认配置,最少 5 个字段即可运行

📦 安装

npm install vextjs

默认使用 Native Adapter(基于 Node.js http.createServer + find-my-way radix trie),零外部 HTTP 框架依赖,性能最优。

如需使用其他 adapter,请额外安装对应框架包:

# Fastify adapter
npm install fastify

# Hono adapter
npm install hono @hono/node-server

# Express adapter
npm install express

# Koa adapter
npm install koa

然后在配置中指定 adapter:

// src/config/default.js
export default {
  adapter: 'fastify', // 'native' (默认) | 'fastify' | 'hono' | 'express' | 'koa'
}

⚡ 性能

VextJS 提供 5 种 adapter,覆盖不同使用场景。以下为基准测试数据(5 轮取中位数):

Native vs Fastify(核心对比)

| 场景 | Raw Native | Vext Native | Raw Fastify | Vext Fastify | Native 领先 | |------|----------:|----------:|----------:|----------:|:----------:| | JSON 响应 | 94,252 | 70,874 | 90,871 | 60,150 | +17.8% | | 路由参数 | 87,660 | ~68,000 | 89,382 | 47,021 | +44.6% | | 中间件链 | 78,100 | 63,158 | 81,126 | 54,707 | +15.4% |

Vext-Native 在所有场景全面领先 Vext-Fastify 15-45%

全 Adapter 性能概览(JSON 场景)

| Adapter | Vext RPS | Overhead | 额外依赖 | 推荐场景 | |---------|--------:|---------:|----------|----------| | Native ⭐ | 70,874 | 24.8% | ✅ 零依赖 | 默认推荐,性能最优 | | Fastify | 60,150 | 33.8% | fastify | 需要 Fastify 生态插件 | | Koa | 42,010 | 31.6% | koa | 已有 Koa 中间件需复用 | | Hono | 26,630 | 37.7% | hono @hono/node-server | Web Standard API 兼容 | | Express | 14,098 | 10.9% | express | 已有 Express 生态需复用 |

测试环境: Node.js v22.13.0 + autocannon(50 connections, 10 pipelining, 10s × 5 轮取中位数, Windows x64, i5-14400, 32GB RAM)

Native adapter 使用 Node.js 内置 http.createServer + find-my-way radix trie 路由,是 VextJS 唯一不依赖第三方 HTTP 框架的 adapter。Vext-Native 比 Vext-Fastify 快 17.8%(JSON)/ 15.4%(中间件链),比 Vext-Hono 快 166%,比 Vext-Express 快 403%。所有数据经 5 轮中位数验证,CV(变异系数)< 1.5%。

Adapter 选择指南

| 你的场景 | 推荐 Adapter | 理由 | |---------|-------------|------| | 新项目,无历史包袱 | native(默认) | 零外部依赖 + 性能最优 | | 已有 Fastify 插件生态 | fastify | 可复用 Fastify 插件(如 fastify-multipart) | | 已有 Express 中间件 | express | 兼容庞大的 Express 中间件生态 | | 已有 Koa 中间件 | koa | 兼容 Koa 中间件 | | 需要 Web Standard API | hono | Hono 支持 Request/Response Web API 标准 |


🚀 快速开始

1. 创建项目结构

my-app/
├── src/
│   ├── config/
│   │   └── default.js       # 应用配置
│   └── routes/
│       └── index.js          # 路由定义
└── package.json

2. 配置 package.json

{
  "name": "my-app",
  "type": "module",
  "scripts": {
    "start": "vext start",
    "dev": "vext dev"
  },
  "dependencies": {
    "vextjs": "^0.1.4"
  }
}

3. 编写配置

// src/config/default.js
export default {
  port: 3000,
  host: '0.0.0.0',
  logger: {
    level: 'info',
  },
  openapi: {
    enabled: true,
  },
}

💡 只需声明你关心的字段,其他字段(requestIdcorsbodyParserrateLimitaccessLog 等)由框架自动补全默认值。

4. 编写路由

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

export default defineRoutes((app) => {
  app.get('/', {}, async (req, res) => {
    res.json({ message: 'Hello, VextJS!' })
  })

  app.get('/health', {}, async (req, res) => {
    res.json({ status: 'ok', uptime: process.uptime() })
  })
})

5. 启动

# 开发模式(热重载)
npm run dev

# 生产模式
npm start
# 验证
curl http://localhost:3000/
# → {"code":0,"data":{"message":"Hello, VextJS!"}}

🖥️ CLI 命令

VextJS 提供内置 CLI,通过 npx vextpackage.json scripts 调用。

vext start — 生产模式

vext start                    # 使用默认配置启动
vext start --port 8080        # 指定端口
vext start --host 127.0.0.1   # 指定监听地址

启动流程:检测项目结构 → 加载配置 → 注册插件/中间件/服务/路由 → 启动 HTTP 服务器。

如果存在 dist/ 编译产物,自动使用编译后的 JS 运行;TypeScript 项目无 dist/ 时自动通过 tsx 加载。

vext dev — 开发模式

vext dev                      # 启动开发服务器
vext dev --poll               # Docker / NFS 环境使用轮询模式
vext dev --poll-interval 2000 # 自定义轮询间隔(毫秒)
vext dev --debounce 200       # 自定义防抖间隔(毫秒)
vext dev --no-hot             # 禁用 Soft Reload,所有变更走 Cold Restart
vext dev --clear              # 每次重载后清空控制台

三层重载策略:

| Tier | 触发条件 | 动作 | 速度 | |------|---------|------|------| | T1 | 代码修改(modify) | Soft Reload — esbuild.transform() 热替换 | ⚡ 毫秒级 | | T2 | 文件新增 / 删除 | Soft Reload — esbuild ctx.rebuild() 重建 | ⚡ 毫秒级 | | T3 | 配置 / 插件 / .env 变更 | Cold Restart — kill + fork 重启子进程 | 🔄 秒级 |

键盘快捷键:

| 按键 | 功能 | |------|------| | r | 手动 Cold Restart | | h | 手动 Soft Reload(全量) | | c | 清空控制台 | | ? | 显示帮助 | | Ctrl+C | 退出开发服务器 |

vext build — 构建

vext build                    # TypeScript 编译为 JavaScript

📁 项目结构

my-app/
├── src/
│   ├── config/
│   │   ├── default.js        # 默认配置
│   │   ├── production.js     # 生产环境覆盖(可选)
│   │   └── local.js          # 本地覆盖,不提交到 Git(可选)
│   ├── routes/               # 路由目录(自动扫描)
│   │   ├── index.js          # → /
│   │   ├── users.js          # → /users
│   │   └── api/
│   │       └── posts.js      # → /api/posts
│   ├── services/             # 服务层(自动注入到 app.services)
│   │   ├── user.js           # → app.services.user
│   │   └── payment/
│   │       └── stripe.js     # → app.services.payment.stripe
│   ├── middlewares/           # 自定义路由级中间件
│   ├── plugins/              # 插件(拓扑排序加载)
│   ├── locales/              # i18n 语言包(可选)
│   │   ├── zh-CN.json
│   │   └── en.json
│   └── ...
├── package.json
└── tsconfig.json             # TypeScript 项目(可选)

🛣️ 路由

路由使用 defineRoutes 定义,支持三段式 (path, options, handler)两段式 (path, handler) 语法。

基础路由

// src/routes/users.js
import { defineRoutes } from 'vextjs'

export default defineRoutes((app) => {
  // 三段式:path, options, handler
  app.get('/list', {
    docs: { summary: '获取用户列表' },
    validate: {
      query: { page: 'number:1-', limit: 'number:1-100' },
    },
  }, async (req, res) => {
    const { page, limit } = req.valid('query')
    const users = await app.services.user.findAll({ page, limit })
    res.json(users)
  })

  // 两段式:path, handler(无 options)
  app.get('/:id', async (req, res) => {
    const user = await app.services.user.findById(req.params.id)
    res.json(user)
  })

  app.post('/', {
    validate: {
      body: { name: 'string:1-50', email: 'email' },
    },
  }, async (req, res) => {
    const user = await app.services.user.create(req.valid('body'))
    res.json(user, 201)
  })

  app.delete('/:id', {}, async (req, res) => {
    await app.services.user.delete(req.params.id)
    res.json({ deleted: true })
  })
})

路由映射规则

| 文件路径 | 路由前缀 | |---------|---------| | src/routes/index.js | / | | src/routes/users.js | /users | | src/routes/api/posts.js | /api/posts | | src/routes/api/v2/orders.js | /api/v2/orders |

路由选项

app.get('/protected', {
  // 路由级中间件引用(需在 config.middlewares 白名单中声明)
  middlewares: ['auth', { name: 'rbac', options: { roles: ['admin'] } }],

  // 参数校验(schema-dsl 语法)
  validate: {
    query: { page: 'number', limit: 'number' },
    params: { id: 'string' },
    body: { name: 'string:1-100', email: 'email' },
  },

  // OpenAPI 文档元信息
  docs: {
    summary: '获取受保护资源',
    description: '需要认证和管理员角色',
    tags: ['Admin'],
  },
}, handler)

🔧 服务层

服务文件放在 src/services/ 下,导出一个 class,框架自动实例化并注入到 app.services

// src/services/user.js
export default class UserService {
  constructor(app) {
    this.app = app
    this.logger = app.logger
  }

  async findAll({ page = 1, limit = 20 }) {
    this.logger.info(`Fetching users page=${page} limit=${limit}`)
    // 数据库查询...
    return { users: [], total: 0 }
  }

  async findById(id) {
    // ...
  }

  async create(data) {
    // ...
  }
}
// 在路由中使用
app.get('/users', {}, async (req, res) => {
  const result = await app.services.user.findAll({ page: 1 })
  res.json(result)
})

嵌套服务

services/
├── user.js              → app.services.user
├── user-profile.js      → app.services.userProfile
└── payment/
    ├── stripe.js         → app.services.payment.stripe
    └── alipay.js         → app.services.payment.alipay
  • 文件名 kebab-case 自动转换为 camelCase
  • _ 开头的文件/目录会被跳过
  • 框架自动检测服务之间的循环依赖

🧩 插件

插件用于扩展框架能力,支持依赖声明和拓扑排序加载。

// src/plugins/redis.js
import { definePlugin } from 'vextjs'
import Redis from 'ioredis'

export default definePlugin({
  name: 'redis',

  // 声明依赖(可选),框架自动按拓扑顺序加载
  // dependencies: ['database'],

  async setup(app) {
    const redis = new Redis(app.config.redis)

    // 扩展 app 对象
    app.extend('cache', redis)

    // 注册全局中间件
    app.use(async (req, res, next) => {
      req.cache = app.cache
      await next()
    })

    // 注册关闭钩子(优雅关闭时执行)
    app.onClose(async () => {
      await redis.quit()
      app.logger.info('Redis disconnected')
    })
  },
})
// 在路由/服务中使用插件扩展的能力
const cached = await app.cache.get('user:123')

🛡️ 中间件

内置中间件

VextJS 内置以下中间件,全部开箱即用,无需手动注册:

| 中间件 | 功能 | 配置字段 | |--------|------|---------| | requestId | 为每个请求生成唯一 ID | config.requestId | | cors | 跨域资源共享 | config.cors | | bodyParser | 请求体解析(JSON / URLEncoded) | config.bodyParser | | rateLimit | 速率限制 | config.rateLimit | | responseWrapper | 统一响应格式 { code, data, message } | config.response | | accessLog | 请求访问日志 | config.accessLog | | errorHandler | 全局错误处理 + 404 兜底 | — |

自定义中间件

// src/middlewares/auth.js
import { defineMiddleware } from 'vextjs'

export default defineMiddleware(async (req, res, next) => {
  const token = req.headers['authorization']
  if (!token) {
    req.app.throw(401, 'Unauthorized')
  }
  // 解析 token,设置用户信息...
  await next()
})

工厂中间件(带配置参数)

// src/middlewares/rbac.js
import { defineMiddlewareFactory } from 'vextjs'

export default defineMiddlewareFactory((options) => {
  return async (req, res, next) => {
    if (!options.roles.includes(req.user?.role)) {
      req.app.throw(403, 'Forbidden')
    }
    await next()
  }
})
// 在路由中使用(需在 config.middlewares 白名单声明)
app.get('/admin', {
  middlewares: [{ name: 'rbac', options: { roles: ['admin'] } }],
}, handler)

⚙️ 配置

配置文件支持三层合并:default{NODE_ENV}local

// src/config/default.js — 默认配置
export default {
  port: 3000,
  host: '0.0.0.0',
  logger: {
    level: 'info',        // 'debug' | 'info' | 'warn' | 'error' | 'silent'
  },
  cors: {
    origins: ['*'],       // 允许的来源列表(数组格式)
    methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
  },
  bodyParser: {
    maxBodySize: '1mb',
  },
  rateLimit: {
    max: 100,             // 每个窗口期最大请求数
    window: 60,           // 窗口期时长(秒,数字)
  },
  requestId: {
    enabled: true,
    header: 'X-Request-Id',
  },
  response: {
    hideInternalErrors: true,   // 生产环境隐藏内部错误详情
  },
  openapi: {
    enabled: true,
    info: {
      title: 'My API',
      version: '1.0.0',
    },
  },
  shutdown: {
    timeout: 10,          // 优雅关闭超时(秒)
  },
}
// src/config/production.js — 生产环境覆盖
export default {
  logger: { level: 'warn' },
  response: { hideInternalErrors: true },
}
// src/config/local.js — 本地开发覆盖(加入 .gitignore)
export default {
  port: 4000,
  logger: { level: 'debug' },
}

CLI 参数 --port / --host 优先级最高,覆盖配置文件中的值。


✅ 参数校验

路由选项中的 validate 字段使用 schema-dsl 语法,声明式校验请求参数。

app.post('/users', {
  validate: {
    body: {
      name: 'string:1-50',           // 字符串,长度 1-50
      email: 'email',                // 邮箱格式
      age: 'number:0-150?',          // 可选数字,范围 0-150
      role: 'enum:admin,user,guest', // 枚举值
      tags: '[string]',              // 字符串数组
    },
    query: {
      format: 'enum:json,xml?',      // 可选枚举
    },
  },
}, async (req, res) => {
  const body = req.valid('body')    // 类型安全的校验后数据
  const query = req.valid('query')
  // ...
})

校验失败时自动返回 400 错误,包含详细的字段错误信息。支持 i18n 多语言错误消息。


📖 OpenAPI 文档

启用 openapi.enabled: true 后,框架自动从路由元信息生成 OpenAPI 3.1 文档。

# 获取 OpenAPI JSON
curl http://localhost:3000/openapi.json

路由的 docs 选项用于补充文档元信息:

app.get('/users/:id', {
  docs: {
    summary: '获取用户详情',
    description: '根据用户 ID 获取完整的用户信息',
    tags: ['Users'],
  },
  validate: {
    params: { id: 'string' },
  },
}, handler)

🧪 测试

VextJS 提供内置测试工具,无需启动 HTTP 服务器即可测试路由。

import { describe, it, expect } from 'vitest'
import { createTestApp } from 'vextjs/testing'

describe('User API', () => {
  it('should return user list', async () => {
    const app = await createTestApp({
      rootDir: '/path/to/project',
    })

    const res = await app.request.get('/users/list?page=1&limit=10')

    expect(res.status).toBe(200)
    expect(res.body.code).toBe(0)
    expect(res.body.data).toBeDefined()
  })
})

🌐 i18n 国际化

src/locales/ 下放置语言文件,框架自动加载并注册到 schema-dsl 校验器。

// src/locales/zh-CN.json
{
  "validation.required": "{field} 不能为空",
  "validation.string.min": "{field} 长度不能少于 {min} 个字符",
  "validation.email": "{field} 格式不正确"
}
// src/locales/en.json
{
  "validation.required": "{field} is required",
  "validation.string.min": "{field} must be at least {min} characters",
  "validation.email": "{field} is not a valid email"
}

🏛️ 架构概览

用户请求
  │
  ▼
┌──────────────────────────────────────────────┐
│               VextJS Framework               │
│                                              │
│  ┌─── 内置中间件链 ───────────────────────┐  │
│  │ requestId → cors → bodyParser →        │  │
│  │ rateLimit → responseWrapper → accessLog│  │
│  └────────────────────────────────────────┘  │
│                    │                         │
│                    ▼                         │
│  ┌─── 路由级中间件 ──┐                       │
│  │ auth → rbac → ... │                       │
│  └───────────────────┘                       │
│                    │                         │
│                    ▼                         │
│  ┌─── 参数校验 ──────┐                       │
│  │ validate(schema)  │                       │
│  └───────────────────┘                       │
│                    │                         │
│                    ▼                         │
│  ┌─── 路由 Handler ──┐  ┌── Services ──┐    │
│  │  app.get/post/... │─→│ app.services │    │
│  └───────────────────┘  └──────────────┘    │
│                    │                         │
│                    ▼                         │
│  ┌─── Adapter Layer ─────────────────────┐   │
│  │  Native (默认) / Fastify / Hono /     │   │
│  │  Express / Koa  — 可替换              │   │
│  └───────────────────────────────────────┘   │
└──────────────────────────────────────────────┘
  │
  ▼
HTTP 响应 → { code: 0, data: {...} }

启动流程

  1. 配置加载default{env}local 三层合并 + 冻结
  2. 创建 App — 初始化 logger、validator、adapter、throw
  3. i18n 加载 — 自动扫描 src/locales/
  4. 插件加载 — 拓扑排序 + 依次 setup()
  5. 中间件加载 — 按 config.middlewares 白名单加载
  6. 服务加载 — 扫描 src/services/,实例化注入 app.services
  7. 路由加载 — 扫描 src/routes/,注册到 adapter
  8. 内置中间件注册 — requestId → cors → bodyParser → rateLimit → responseWrapper → accessLog → errorHandler
  9. HTTP 监听adapter.listen(port, host)
  10. 就绪钩子 — 执行 onReady 回调

📋 环境变量

| 变量 | 说明 | 默认值 | |------|------|--------| | NODE_ENV | 运行环境 | production(start)/ development(dev) | | VEXT_PORT | 覆盖监听端口 | — | | VEXT_HOST | 覆盖监听地址 | — | | VEXT_DEV_POLL | 强制轮询模式(1 / 0) | 自动检测 | | VEXT_DEV_NO_HOT | 禁用 Soft Reload | — | | VEXT_DEV_DEBOUNCE | 防抖间隔(毫秒) | 100 |


🗺️ 路线图

  • [x] Adapter 架构(Native 默认 + Hono / Fastify / Express / Koa 可选)
  • [x] Native Adapter(零外部依赖,http.createServer + find-my-way radix trie)
  • [x] 约定式路由 + 三段式语法
  • [x] 插件系统(拓扑排序 + 生命周期)
  • [x] 服务自动注入
  • [x] 内置中间件(requestId / CORS / bodyParser / rateLimit / accessLog)
  • [x] 参数校验(schema-dsl 集成)
  • [x] OpenAPI 3.1 文档生成
  • [x] CLI(start / dev / build / stop / reload / status)
  • [x] 开发模式热重载(Soft Reload + Cold Restart)
  • [x] 测试工具(createTestApp)
  • [x] Cluster 多进程(Master/Worker + Rolling Restart)
  • [x] 性能基准测试(autocannon 自动化 + 多轮取中位数)
  • [x] AsyncLocalStorage 可配置跳过
  • [x] Native Adapter 性能优化(Overhead 降至 ~20%,领先 Fastify 15-45%)
  • [x] vext create 项目脚手架
  • [x] 文档站(rspress)
  • [ ] SSE 支持
  • [ ] WebSocket 支持

🤝 贡献

欢迎提交 Issue 和 Pull Request。

# 克隆项目
git clone https://github.com/vextjs/vext.git
cd vext

# 安装依赖
npm install

# 开发(TypeScript 监听编译)
npm run dev

# 运行测试
npm test

# 类型检查
npm run typecheck

# 构建
npm run build

📄 许可证

MIT © 2025 vextjs