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

@qordli/next-express

v0.1.6

Published

A file-based routing compiler for express, inspired by Next.js.

Readme

next-express

一个受 Next.js 启发的 Express 文件系统路由编译器。将 src/ 下的约定式目录结构编译为一个可直接启动的 Express 服务器入口,从而快速获得:

  • 约定式 app 目录 + route.(ts|js) API 路由
  • 逐层继承的中间件 (middlewares.(ts|js) / tail-middlewares.(ts|js))
  • 全局 settings.(ts|js) (批量调用 app.set)
  • 自定义服务端入口(可选 custom-server.(ts|js)
  • 开发模式实时 watch + 自动重编译 + 热启动
  • 生产模式打包(基于 tsup,目标 Node 22,ESM)

本仓库同时提供 Rust 实现的二进制(性能更好)以及 TypeScript 纯实现回退。主 CLI 名称:next-express;TS 回退编译器 CLI:nexp-compiler-ts

安装

# 或者你可以使用任何你喜欢的包管理器
pnpm add -D next-express ts-morph tsup chokidar
pnpm add express

基本概念与目录约定

运行 next-express 构建出来的代码你需要以下环境

  • node.js >= 22
  • express (next-express 导出 express 为 peerDependencies, 你需要自己安装)

开发模式下解析 next-express 提供的工具函数你需要进行以下设置

  • tsconfig 的 module 为 node16 及以上
  • package.json 的 type 设置为 module
nexp-compiled/
	server.ts               # (编译产物) createServer 实现 (默认编译输出)
	index.ts                # (编译产物) 启动脚本 (监听端口等)
src/
	app/
		user/
			route.ts            # /user
			middlewares.ts      # 作用于 user/ 及其子层所有路由 (进入 user/ 子树后最先执行)
		health/
			route.ts            # /health
		(group)/
			stats/
				route.ts          # /stats  (括号包裹目录属于“虚拟分组”,不会出现在最终路径中)
		route.ts              # /        (根路由)
	middlewares.ts          # 顶层全局中间件 (app.use(...))
	tail-middlewares.ts     # 尾部中间件/兜底处理 (如 404、错误收集)
	settings.ts             # 导出配置数组, 用于 app.set
	custom-server.ts        # (可选) 自定义 createServer/启动逻辑,存在时直接拷贝使用

文件说明

| 文件/模式 | 作用 | | ----------------------------- | ------------------------------------------------------------------------------------------------------------- | | app/**/route.(ts\|js) | 定义一个 API 路由,导出 HTTP 方法函数 (GET/POST/PUT/DELETE/PATCH/OPTIONS/HEAD 等)。 | | app/**/middlewares.(ts\|js) | 导出数组:[(req,res,next)=>{}|(err,req,res,next)=>{}],对该目录与子目录所有路由生效,形成分层子 Router。 | | middlewares.(ts\|js) | 顶层全局中间件数组。 | | tail-middlewares.(ts\|js) | 顶层尾部中间件/404/错误处理。 | | settings.(ts\|js) | 导出形如:export const settings = [{ name: 'trust proxy', value: true }]。 | | custom-server.(ts\|js) | 若存在,则使用该文件生成代码(需自行导出 createServer 函数)。 |

路由导出约定

route.ts 中导出 HTTP 方法(方法名大小写敏感,与 Express 对应):

// src/app/user/route.ts
export const GET = async (req, res) => {
	res.json({ user: 'alice' });
};

export const POST = async (req, res) => {
	res.status(201).send('created');
};

若一个方法未导出,请求将返回 405 Method Not Allowed

虚拟分组目录

以括号包裹命名的目录 (group) 仅用于逻辑分组,不参与实际 URL。src/app/(internal)/logs/route.ts 将对应 /logs

CLI 使用 (next-express)

编译器会生成:

  • nexp-compiled/server.ts (或自定义 server 文件名)
  • .next-express/index.js (构建/开发最终执行入口)

命令总览

| 命令 | 说明 | 典型场景 | | -------------- | -------------------------------------------------- | -------------- | | dev | 开发模式:watch 编译 + 自动启动 Node 进程 | 本地开发 | | compile | 仅生成编译产物 (不打包、不压缩) | 调试、二次加工 | | build | 生成编译产物并用 tsup 打包、压缩到 .next-express | 生产部署 | | -v/--version | 查看版本 | —— |

通用参数

| 参数 | 默认 | 说明 | | --------------- | --------------- | ----------------------------------------- | | --src-dir | src | 源码目录 | | --dist-dir | nexp-compiled | 中间编译输出目录(server 模板) | | --server | server.ts | 生成的 server 文件名(包含 createServer) | | --entry | index.ts | 生成的入口启动文件名(会监听端口) | | --port / -p | 3000 | 启动端口(写入入口文件) |

dev 额外参数:

| 参数 | 默认 | 说明 | | --------- | --------- | --------------------- | | --watch | ['src'] | 监听变更目录/文件列表 |

典型流程

# 开发
npx next-express dev -p 4000

# 仅编译(生成 nexp-compiled/server.ts nexp-compiled/index.ts)
npx next-express compile

# 生产构建(输出 .next-express/index.js,可直接 node 运行)
npx next-express build

# 运行打包后产物
node .next-express/index.js

开发模式说明

dev 模式内部:

  1. 调用编译逻辑(扫描目录 + 生成 server 模板 + 入口文件)。
  2. 启动 tsup watch,对生成入口进行打包输出到 .next-express
  3. 编译成功后执行 node .next-express/index.js
  4. 文件改动 → 重复 1-3,达到近似热重载体验。

输出模板示意

生成的 server.ts 类似:

import express from 'express';
// 动态插入的 imports...

export const createServer = () => {
	const app = express();
	// settings, middlewares, routes, tail-middlewares 注入
	return app;
};

生成的入口(index.ts)会:

import { createServer } from './server';

const app = createServer();
app.listen("<port>", () => {
	console.log('Server is listening on <port>');
});

自定义 server

src/ 直接放置 custom-server.ts(或 .js)即可

注意其中必须包含以下魔法注释,会在编译时被替换为真实代码

  • /* __nextExpress_imports__ */
  • /* __nextExpress_settings__ */
  • /* __nextExpress_topLevelMiddlewares__ */
  • /* __nextExpress_routes__ */
  • /* __nextExpress_tailMiddlewares__ */

例如你想挂载 socket.io 服务器:

import express from "express";
import { Server as SioServer } from "socket.io";
import { createServer as CreateHttpServer } from "http";
/* __nextExpress_imports__ */

export const createServer = () => {
  const app = express();

  /* __nextExpress_settings__ */

  const server = CreateHttpServer(app);
  const io = new SioServer(server);
  io.on("connection", (socket) => {
    console.log("New socket connection:", socket.id);
  });

  /* __nextExpress_topLevelMiddlewares__ */

  /* __nextExpress_routes__ */

  /* __nextExpress_tailMiddlewares__ */
  return app;
};

存在该文件时,编译流程会直接使用它作为模板文件。

Method Not Allowed 处理

若访问的路由未实现当前 HTTP 方法,会自动返回:

405 Method <METHOD> Not Allowed

(内部代码:res.status(405).send(`Method ${req.method} Not Allowed`))。

常见问题 (FAQ)

1. 为什么我的目录不生效?

  • 确保在 src/app/ 下。
  • 只识别 route.(ts|js) 作为终端路由文件。
  • 虚拟分组必须使用括号包裹整个目录名,如 (auth)

2. 中间件执行顺序?

  1. 顶层 middlewares.ts
  2. 分层目录 app/**/middlewares.ts(由外到内)
  3. 路由处理函数(GET/POST...)
  4. 顶层 tail-middlewares.ts

3. 如何添加 404?

tail-middlewares.ts 最后添加:

export const middlewares = [
	(req, res) => res.status(404).send('Not Found')
];

4. 如果添加全局错误处理?

5. 如何扩展生成逻辑?

  • 使用 custom-server.ts 完全接管生成
  • 引用生成后的 server.ts 文件自定义入口文件

许可证

MIT