跳到主要内容

core - 核心

核心模块用于模块的加载与服务启动

依赖模块

配置项

配置项类型默认值功能
envstringdevelopment执行环境,开发环境为 development 生产环境为 production,一般通过 NODE_ENV 环境变量指定
keysstring[]Cookie 签名密钥
proxybooleanfalse信任代理头信息,例如前级为 Nginx 为了取得真实客户端 ip 地址需要设置为 true
subdomainOffsetnumber子域名位置
proxyIpHeaderstringX-Forwarded-For代理后客户端真实 ip 头字段名
maxIpsCountnumber0多级代理后允许的 ip 数量,0 无限制

Core 挂载项

挂载项类型功能
namestring应用名称,获取顺序: env.APP_NAME、hostname
startTimenumber启动时间: 毫秒时间戳
appKoa取得 Koa 实例
loadedModulesLoadedModule[]已载入的模块
serverServer取得 http.Server 实例
debugDebuggercore debug 方法

Context 挂载项

挂载项类型功能
coreCoreCore 模块实例

全局方法 [v4.0+]

通过全局方法可以在任何地方获取 Core 实例和当前请求上下文,不再需要层层传递参数。

名称功能
$initCore(opt?)初始化全局 Core 实例,默认启用 asyncLocalStorage。如果实例已存在则抛出异常
$getCore()取得全局 Core 实例。如果实例不存在则抛出异常
$core$getCore() 的快捷方式,通过 Proxy 代理访问 Core 实例的属性和方法
$getContext(force?)取得当前请求上下文。force 默认为 true,无法取得时抛出异常;设为 false 则返回 undefined
$ctx$getContext() 的快捷方式,通过 Proxy 代理访问 Context 的属性和方法
$debug / createDebug带有请求信息和调用位置信息的 debug 输出工具,支持 extend() 扩展命名空间
import { $initCore, $getCore, $core, $getContext, $ctx, $debug } from '@zenweb/core';

// 初始化全局 Core 实例(通常在入口文件中调用一次)
const core = $initCore();

// 在任意位置取得 Core 实例
$core.name; // 等同于 $getCore().name

// 在请求处理链中取得当前请求上下文
$ctx.path; // 等同于 $getContext().path

// 带有请求信息和调用位置信息的 debug 输出
$debug('查询参数: %o', $ctx.query);

// 扩展 debug 命名空间
const myDebug = $debug.extend('mymod');
myDebug('自定义模块日志');

自定义模块入口样例代码

import { SetupFunction } from '@zenweb/core';

// 自定义模块配置项
export interface MyModOption {}

// 是否有 opt 参数或者其他参数由模块开发者自定义
export default function (opt?: MyModOption): SetupFunction {
// 返回函数的名称将作为模块名称显示
return function mymodname(setup) {}
}

SetupHelper 完整 API

SetupHelper 是模块安装时的核心助手对象,在模块安装函数中作为参数传入,提供了丰富的 API 用于扩展框架能力。

defineCoreProperty(prop, descriptor)

在 Core 实例上定义属性。如果属性已存在则抛出异常,防止模块间冲突。

import { SetupFunction } from '@zenweb/core';

export default function mymod(setup: SetupFunction) {
return function mymod(setup) {
// 定义 Core 上的属性
setup.defineCoreProperty('myService', {
value: new MyService(),
});

// 也可以使用 getter 实现延迟初始化
setup.defineCoreProperty('config', {
get() {
return loadConfig();
},
});
};
}

defineContextProperty(prop, descriptor)

在请求上下文 (Context) 上定义属性。每个请求都可以访问该属性。如果属性已存在则抛出异常。

import { SetupFunction } from '@zenweb/core';

export default function (): SetupFunction {
return function mymod(setup) {
// 在 Context 上定义方法
setup.defineContextProperty('getUserId', {
value: function () {
return this.headers['x-user-id'];
},
});

// 定义 getter 属性
setup.defineContextProperty('clientIp', {
get() {
return this.ip || this.ips?.[0];
},
});
};
}

defineContextCacheProperty(prop, getter)

在 Context 上定义懒缓存属性。属性第一次被访问时执行 getter 函数,之后直接返回缓存值。每个请求独立缓存,适合在请求生命周期内多次访问的耗时操作。

import { SetupFunction } from '@zenweb/core';

export default function (): SetupFunction {
return function mymod(setup) {
// 第一次访问时创建数据库连接,后续复用缓存
setup.defineContextCacheProperty('dbConn', (ctx) => {
setup.debug('创建数据库连接');
return createConnection(ctx.core.dbConfig);
});

// 第一次访问时解析用户信息
setup.defineContextCacheProperty('currentUser', async (ctx) => {
const token = ctx.headers['authorization'];
if (!token) return null;
return verifyToken(token);
});
};
}

middleware(fn)

注册全局中间件,等同于 app.use(middleware)。中间件按照模块加载顺序执行。

import { SetupFunction, Context, Next } from '@zenweb/core';

export default function (): SetupFunction {
return function mymod(setup) {
setup.middleware(async function myMiddleware(ctx: Context, next: Next) {
console.log('请求开始:', ctx.path);
await next();
console.log('请求结束:', ctx.status);
});
};
}

after(fn)

注册回调函数,在所有模块初始化完成后执行。适合需要依赖其他模块已完成初始化的场景。

import { SetupFunction } from '@zenweb/core';

export default function (): SetupFunction {
return function mymod(setup) {
setup.after(async () => {
// 所有模块都已加载完毕,可以安全使用其他模块提供的功能
setup.debug('所有模块初始化完成');
});
};
}

destroy(fn)

注册销毁回调,在服务停止时调用。框架会等待销毁方法完成后再关闭连接。适合释放资源(如数据库连接、文件句柄等)。

import { SetupFunction } from '@zenweb/core';

export default function (): SetupFunction {
return function mymod(setup) {
let connection: DatabaseConnection;

setup.after(async () => {
connection = await createConnection();
});

// 服务停止时关闭连接
setup.destroy(async () => {
if (connection) {
await connection.close();
setup.debug('数据库连接已关闭');
}
});
};
}

assertModuleExists(name, msg?)

断言指定模块已安装,如果不存在则抛出异常。用于在模块安装阶段声明依赖关系。

import { SetupFunction } from '@zenweb/core';

export default function (): SetupFunction {
return function mymod(setup) {
// 检查必需的依赖模块
setup.assertModuleExists('inject', 'mymod 模块需要先安装 @zenweb/inject');
setup.assertModuleExists('controller');

// 模块初始化逻辑...
};
}

Core 生命周期

Core 模块定义了完整的应用生命周期,按照 boot → start → stop 的顺序执行。

boot - 模块初始化

boot() 方法按模块加载顺序依次执行所有模块的安装函数,之后执行所有通过 after() 注册的回调。

import { Core } from '@zenweb/core';

const core = new Core();
core.setup(moduleA);
core.setup(moduleB);

// 执行所有模块的 setup 函数,然后执行所有 after 回调
await core.boot();

start - 启动服务

start() 方法依次执行 boot()listen() → 注册信号处理。

import { Core } from '@zenweb/core';

const core = new Core();
core.setup(moduleA);
core.setup(moduleB);

// 启动应用:初始化模块 → 监听端口 → 注册信号处理
// 默认端口 7001,也可通过环境变量 PORT 指定
await core.start(3000);

stop - 停止服务

stop() 方法按照模块加载的逆序依次调用各模块的 destroy() 回调,确保资源正确释放。

import { Core } from '@zenweb/core';

const core = new Core();
// ...
await core.start();

// 手动停止服务(通常由信号触发,不需要手动调用)
await core.stop();

信号处理

start() 启动后会自动注册 SIGTERMSIGINT 信号处理,收到信号后触发优雅关闭流程。

// 应用启动后,以下方式可以触发停止:
// - 发送 SIGTERM 信号:kill <pid>
// - 发送 SIGINT 信号:Ctrl+C(终端模式)
// - Docker/K8s 发送停止信号

优雅关闭

Core 内置了优雅关闭(Graceful Shutdown)机制,确保服务停止时不会丢失正在处理的请求:

  1. 停止接收新请求:关闭 HTTP 服务器监听,不再接受新的连接
  2. 按逆序销毁模块:按照模块加载的相反顺序,依次调用各模块的 destroy() 回调,等待每个模块清理完成
  3. 防重复处理:通过 _stopping 标记防止重复触发关闭流程
  4. 强制退出保护:如果在关闭过程中再次收到停止信号,会打印当前活跃资源信息并强制退出
import { $initCore } from '@zenweb/core';

const core = $initCore();
core.setup(function mymod(setup) {
setup.destroy(async () => {
// 在这里释放模块持有的资源
// 例如关闭数据库连接、停止定时任务等
// Core 会等待此方法完成后继续关闭流程
});
});

await core.start();
// 收到 SIGTERM/SIGINT 信号后自动触发优雅关闭