@astroscope/node

中文文档
5.0.1发布于 2026/11/03MITTypeScriptES Module构建来源已验证近 30 天下载 1968

对Astro来说,有观点的、对云友好的节点适配器:靴子生命周期、健康探测器、请求日志、遥测、CSRF和静态服务在服务器周围运行,作为普通代码。listen()

中文使用文档
文档目录23 节
  1. 它会做什么
  2. 它不做的——当心
  3. 使用量
  4. 启动上下文访问
  5. 生命周期事件
  6. 平台条目文件
  7. 日志
  8. 报告路线
  9. 遥测
  10. 健康检查
  11. 原生山顶
  12. 警卫
  13. 现有警卫
  14. 排除图案
  15. 岛屿预装
  16. 预压缩静态服务
  17. 嵌入式建构扭矩
  18. 图像处理
  19. 选项
  20. HTTPS (韩语)
  21. 环境变量
  22. 关闭序列
  23. 许可证

@ 天文台/ 节点

对Astro来说,有观点的、方便云态的节点适配器:靴子生命周期、健康探测器、请求伐木、遥测、CSRF和静态电码 server.listen()。 。 。 .

它会做什么

  • 靴子生命周期 —— 说 onStartup 在端口打开前运行, onShutdown 在飞行中请求排出(src/boot.ts(中文(简体) )
  • 温暖 页面、中间软件和动作与启动同时装入,等待到 listen()
  • 卫生探测器 · 库伯内特式活地/准备在单独的港口,并有可登记的检查
  • 请求日志 – 本地处理器的pino: 真实状态代码, 响应大小, ttfb, 中止连接, 包含静态响应
  • 遥测 – OpenTeleometry NodeSDK, undici 取取仪表, 运行时间 + 主机度量器, Prometheus 读取器
  • CSRF 保护 ——对不安全方法进行来源检查,并排除路径
  • 路径重定向 重复鞭打(//about和一条前后相悖的斜线 trailingSlash (单位:千美元)/about/) 重定向到 Cononic URL, 在 dev 和 prod 中( Astro 的 dev 服务器以 404 页来回答 )
  • 平台条目文件 装入 src/config.ts → src/instrumentation.ts → src/log.ts + 启动, 当文件存在时, 每个自动拾取
  • 岛屿预装 ——每个岛屿的JS预先被平行地装入,而不是被模块所发现的模块,去除水分请求瀑布(英语:Hydrization request waterfall)岛屿预装(中文(简体) )
  • 预压缩静态服务 ——建设时brotli/gzip变体,按 Accept-Encoding
  • 原生山顶 - http-native处理器(oidc-provider, ACME)安装在适配器的服务器上
  • 构建微调 ——安全部门改革源图
  • 图像处理关闭, 除非配置 - 没有明确 image.service,任意 astro:assets 使用大出声失败, 而不是打开 astro 的点名尖端(图像处理(中文(简体) )
  • Dev 重新启动机械 —— 启动文件或条目接合的更改, 在控件页后重新启动 dev 服务器
  • 德夫岛暖和 —— 说 .astro 扫描源 client:* 组件; 它们的分解预优化, 它们的模块图在服务器启动时被取暖, 防止了 Vite 懒惰的分解发现的"504 过期优化 Dep"水分失败
  • HTTPS 促进发展 —— 说 SERVER_CERT_PATH 编号 : SERVER_KEY_PATH 直接为已建服务器的本地运行服务 TLS ()HTTPS (韩语));在生产中,在入侵时终止 TLS

它不做的——当心

适配器假设负载平衡器/倒置代理(Kubernetes, Docker + ingress)后有容器. 在那个设置之外,有几起违约对你是错误的:

  • 打开 0.0.0.0:9090 生产 - 健康探测器服务器 标本的诱饵; 不要公开曝光.
  • 打开 0.0.0.0:9464 生产 ——"普罗米修斯"的读取器. 相同:只有集群内部.
  • 信任任意 Host 编号 : X-Forwarded-Host - 套装 security.allowedDomains: [{}] 除非你自己设定, 因为反向代理将控制这些信头 。 如果没有一个,主机头注射是可能的.
  • 信托基金 X-Forwarded-For ——任何在客户端地址上按键的,都会按照收到时的写法使用信头,因为反向代理有望设置. 直接被曝光,客户端可以自行发送.
  • 覆盖 Astro 安全和配置默认 —— 说 security.checkOrigin: false (嵌入式CSRF中件替换;); csrf: false 恢复Astro的检查, build.redirects: false (运行时处理的指令), trailingSlash: 'never' (只在你的默认情况下) 'ignore', (中文(简体) ), astro:assets 禁用时 image.service 处于默认状态( n)图像处理) (中文(简体) ).
  • 将请求机构限制为1个小米B ——包含每个请求的Astro手柄,页面和端点,不仅仅是Astro所做的动作. 需要上传路径 bodySizeLimit (不涵盖本土山地).
  • 独立而已. 没有中间软件模式——适配器总是拥有服务器.
  • 没有会话驱动程序 . Astro 会话不支持, 除非您配置 session.driver 你自己来.
  • 没有健康探测器. 健康服务器只存在于生产和 astro preview。 。 。 .

使用量

// astro.config.ts
import node from '@astroscope/node';
import { defineConfig } from 'astro/config';

export default defineConfig({
  output: 'server',
  adapter: node(),
});
// src/boot.ts — picked up automatically (or src/boot/index.ts)
import type { BootContext } from '@astroscope/node';

export async function onStartup(context: BootContext) {
  // connect to databases, warm caches, schedule timers
}

export async function onShutdown() {
  // close connections, clear timers
}

astro preview 运行全程生产路径(启动,热身,健康,静态服务).

在dev中,启动文件和下面的条目文件会通过适配器自己的手表/启动机械运行:对启动文件的修改,其依赖图,或者在新一代准备好后释放的持有页后重启dev服务器.

启动上下文访问

服务器代码(包括库)的任何地方, getBootContext() 返回运行中的服务器 BootContext -或者说 undefined 当在此过程中没有启动@astroscope/node服务器时(单位测试,一次性脚本). 图书馆可以使用它来适应dev模式而无需让消费者通过线程来通过:

import { getBootContext } from '@astroscope/node/boot';

const dev = getBootContext()?.dev ?? false;

它被印出在平台入站文件和后起站运行寿命周期之前,无论是prod和dev(每dev重启生成一次重印).

生命周期事件

一个需要启动或关闭的图书馆 站点里没有一条线 src/boot.ts 监听 @astroscope/node/events数字 : on(event, handler) 财务报告和审定财务报表 off(event, handler) 页:1 beforeOnStartup, (中文(简体) ), afterOnStartup, (中文(简体) ), beforeOnShutdown 财务报告和审定财务报表 afterOnShutdown操作者得到 BootContext,按登记顺序运行,并逐一等待; afterOnShutdown 即使当 onShutdown 抛出.

import { on } from '@astroscope/node/events';

on('beforeOnShutdown', async () => {
  await flushPendingWork();
});

平台条目文件

再说 src/boot.ts,另外三个文件在存在时会自动取出. 在生产过程中,它们按照这种顺序在内部运行 startServer(),先于其他任何东西;在dev中,它们每重启生成一次重运行(每个进程只运行一次仪器):

env loading → src/config.ts → src/instrumentation.ts → src/log.ts → boot → warmup → listen

信封装入数字 : CONFIG_PATH (原始内容存档于2018-10-21) (中文(简体) ). env var ./.env 没有。 现有进程env vars胜出;每个结果都有记录.

src/config.ts —— schema + 负载(如@entwico/zod-conf),无其他;导入时验证运行. 故障时:在生产中,缓冲日志会随着出错被倾倒到控制台上,过程会输出出 1;在dev中,启动门会随着出错而使持有页面保持上行.

// src/config.ts
import zc from '@entwico/zod-conf';

export const config = zc.define({ MONGO_URL: zc.env('MONGO_URL').string() }).load({ env: process.env });

src/instrumentation.ts ——只增加仪器(标准捆绑是平台默认,参见遥测). 每个进程装入后——dev重启是在进程内,因此此处的更改需要全dev服务器重启.

// src/instrumentation.ts
import type { InstrumentationContext } from '@astroscope/node';

export function register(ctx: InstrumentationContext) {
  // register additional instrumentations, processors, exporters
}

src/log.ts - 皮诺伐木机 选项 (静态物体或工厂),绝不是日志实例. 平台在仪表设计后自行构建日志,并添加了该邮票的混音 trace_id编号 :span_id编号 :trace_flags 当一个跨度活动时, 在每个条目上。 此文件在 env 加载后运行 src/config.ts,所以选项可以安全读取配置.

// src/log.ts
import type { LoggerOptions } from '@astroscope/node/log';

export default {
  base: { app: 'my-app' },
} satisfies LoggerOptions;

选项取决于运行时上下文时使用厂房窗体 :

// src/log.ts
import type { LoggerOptionsFactory } from '@astroscope/node/log';

const factory: LoggerOptionsFactory = ({ dev }) => ({
  level: dev ? 'debug' : 'info',
});

export default factory;

日志

这个 log 代理是request-aware:在请求中,其条目带有请求绑定(reqId, (中文(简体) ), req在外边,他们去 根伐木机.

import { log } from '@astroscope/node/log';

log.info('handling request');
log.info({ userId: 123 }, 'user logged in');
log.error(err, 'operation failed');

const dbLog = log.child({ component: 'db' });

日志构建前记录的条目(env加载、配置、仪器)被缓冲(Cap 100),一旦施工完成就重新播放——原始时间戳被保留为一种 bufferedTime 字段。 如果在日志存在前启动已死,缓冲器会连同出错一起倒入控制台.

请求日志发生在本地处理器上 finish编号 :close:真实状态代码,响应大小, ttfb,中止的-vs-完成,以及路径模式。 来了 x-request-id 头被通过(并在反应中反射出);否则产生一个短的id.

适配器发送的响应本身会获得自己的路由标签: static 用于客户端目录(公共资产,预发页,200页和304页)提供的文件, duplicate-slashes 财务报告和审定财务报表 trailing-slash 以便他们指示正道, body-limit 给一个被拒绝的尸体 和一个土生土长的山地 name 为可观察性.

报告路线

路由来自路由 Astro 匹配, 对于服务于请求 Astro 的中间软件来说是错误的, 它没有页面—— 一个通过 astro 重写 next(url),或回答自己。 天体匹配 /404 因此,请求被记录和计量为: /404。 。 。 . overrideRequestRoute 让中间软件报告它实际服务的内容:

import { overrideRequestRoute } from '@astroscope/node/log';
import type { MiddlewareHandler } from 'astro';

export const onRequest: MiddlewareHandler = (ctx, next) => {
  const page = lookupPage(ctx.url.pathname);

  if (!page) return next();

  overrideRequestRoute('/cms/pages/[id]');

  return next(`/cms/pages/${page.id}`);
};

此定义将日志行、 度量符和服务器横跨整个名称 。 通过一个模板化的标签,而不是一个混凝土路径,所以度量的红外线保持不变。 一条被推翻的路线总是胜过一个天体匹配的路线,不管中间的软件订单如何.

适配器本身在启动时就发出一条精确的信息线—— server ready { host, port, health, bootMs, warmupMs, totalMs } - 和 draining 编号 : shutdown complete { drainMs } 下来的路上。 其他的都是调试或出错级别.

遥测

node({ telemetry }) 标准捆绑船:NodeSDK,通过undici获取仪器(基于诊断的频道-否) --import ),节点运行时间+主机度量,以及一个普罗米修斯读取器 0.0.0.0:9464。 。 。 . Prod:默认使用. Dev: 默认关闭 (选择与 telemetry: { dev: true }) (中文(简体) ).

  • 服务器从本地处理器开始, 并提取 W3C 上下文; 路由模式和跨度名称由内部中间软件来丰富
  • url.query 带查询字符串,其值为 redactedQueryParams 改为 REDACTED,默认情况下,OpenTeleometter的语义学公约(导出为 OTEL_REDACTED_QUERY_PARAMS; 查询字符串中的应用程序密钥( oauth) code,重设 token需要补充。 这同样适用于 query 请求扩展日志
  • 请求参数 : http.server.request.duration, (中文(简体) ), http.server.active_requests, (中文(简体) ), astro.action.duration (单位:千美元)astro.action.name 是注册名称,任何其他 /_actions/ 路径计数为 unknown); 取出来自未编辑仪器的度量衡
  • astro.render.failures {http.route} 计数使状态出局后失败; 响应被截断在电线上, 请求日志行读取 request truncated 错误级别和服务器跨度 astro.response.truncated
  • 靴子生命周期得到 startup (与 boot编号 :warmup编号 :listen 儿童)和 shutdown (与 drain编号 :onShutdown横跨
  • 追踪出口商受标准驱动 OTEL_* env vars; 没有配置的 OTLP 端点, 追踪默认导出到 none (没有失败的本地主机出口)
  • OTEL_SDK_DISABLED=true 把SDK完全关掉
  • 其它的天文镜包通过相同的SDK记录,是没有它的"无"——他们的仪器被记录在他们身上: @astroscope/react, (中文(简体) ), @astroscope/wormhole, (中文(简体) ), @astroscope/i18n

没有用于跟踪服务器- 递归部分的帮助: 测量子树的渲染值需要缓冲, 从而禁止流出 。 环绕正前题等待 tracer.startActiveSpan() 从 @opentelemetry/api 相反,这就是时间的所在, 它在请求下筑巢,不接触溪流.

健康检查

服务器编码中任何地方的登记检查——一般 onStartup数字 :

import { registerHealthCheck } from '@astroscope/node/health';

export async function onStartup() {
  const db = await connectMongo();

  registerHealthCheck({ name: 'mongo', check: () => db.ping() });
}
  • 探测器按顺序翻转: 启动时直播, 仅在之后准备 listen()排水开始于关闭信号到达时
  • 投出或返回时检查失败 { status: 'unhealthy' }; 无法按要求进行检查 readyz 健康( 健康)optional: true 支票不会影响它, timeout 默认为 5s)
  • registerHealthCheck 返回一个未注册的函数,但清理是可选的:在检查后仍然注册 onShutdown 自动删除
  • 当没有健康运行时间活动(dev模式, health: false),注册为无-op——启动文件中不需要dev/prod分支

原生山顶

对于需要真实的节点库 (req, res) —— 说 oidc-provider是因为 callback(),ACME挑战处理器——将其挂入适配器的服务器上,而不是在天体中间软件内装出节点对象:

// src/boot.ts
import { mountNativeHandler } from '@astroscope/node/native';

export function onStartup() {
  mountNativeHandler({ prefix: '/oidc', name: 'oidc' }, getOidcProvider().callback());
}
  • 处理器完全拥有响应: 匹配的请求在静态服务前发出, 并且永远无法到达天体中端软件或渲染, 因此机器端点不需要 csrf 排除
  • 处理者得到真正的请求和回应:流体, socket.remoteAddress,设置曲奇阵列
  • 请求留在请求内进行记录和追踪; name 成为日志、 参数和横跨名称的路由标签
  • 与 dev 中的相同
  • 匹配 : prefix (部分意识到,最长的胜利)或 match(req) 按登记顺序,在前缀后咨询上游
  • 返回一个未注册的函数;挂载在之后自动清除 onShutdown (在dev重启的世代之间)
  • 处理器错误会被记录并用500个(除非处理器已经发送了头)进行回答

警卫

Astro没有路由守护:中间软件是全球的,只看到路由模式,一个页面的输出在运行前没有被加载. @astroscope/node/guards 将保护放在请求登陆的地方,与类型相匹配:警卫要么否认要么证明某事,以及它证明的要求 locals 仅限警戒密码. App.Locals 保持诚实的形状(user?: User) (中文(简体) ).

// src/guards.ts
import { defineGuard, deny } from '@astroscope/node/guards';

export const authenticated = defineGuard({
  name: 'authenticated',
  check: (ctx) => ({ user: ctx.locals.user ?? deny('UNAUTHORIZED') }),
  page: (ctx) => ctx.redirect('/login'),
});

// runs after `authenticated`, with `ctx.locals.user` already required
export const admin = authenticated.extend({
  name: 'admin',
  check: (ctx) => {
    if (!ctx.locals.user.roles.admin) deny('FORBIDDEN');
  },
  page: (ctx) => ctx.rewrite('/404'),
});

deny(code, message?) 丢出一个 ActionError;返回的对象是证明。 警卫也可以装入一次并交给打过字的人(check: async (ctx, { projectId }) => ({ project: await loadProject(...) })),宣布它所需要的请求字段 input (一作zo.

采取的行动 guards 代替阿斯特罗的 defineAction (单位:千美元) no-astro-define-action 提示规则强制导入). 保护人员在输入验证后运行;他们所申报的字段被合并到计划中,并在操作者面前再次剥离:

import { defineAction } from '@astroscope/node/guards';
import { z } from 'astro/zod';
import { admin } from '../guards';

export const server = {
  rename: defineAction({
    input: z.object({ projectId: z.string(), name: z.string() }),
    guards: [admin],
    handler: async (input, ctx) => {
      ctx.locals.user; // User, not User | undefined
    },
  }),
};

端点包裹的方式相同。 只有在名单中的警卫宣布时才能阅读尸体 input,然后它的字段来自json或成形体:

import { defineRoute } from '@astroscope/node/guards';
import { admin } from '../../guards';

export const POST = defineRoute({
  guards: [admin],
  handler: async (ctx) => Response.json({ by: ctx.locals.user.id }),
});

页面的前题是处理器,所以它询问并返回:

---
import { guard } from '@astroscope/node/guards';
import { admin } from '../guards';

const { denied, user } = await guard(Astro, [admin]);

if (denied) return denied;
---

检查之后 user 要求,在选择之前.

每个表面都有拒绝请求的答案:浏览器导航(text/html 内 Accept得到拒绝的警卫 page 响应, 上面的登录重定向或重写 404 , 或当警卫没有消息时, 与信件的状态; 任何其他呼叫者都会收到 { error: { code, message } } 与状态。 父母一方在下列情况下提出的拒绝 extend() 链条保存父的 page 处理者.

整个区域都从中间的软件上守卫着 同样的警卫和同样的拒绝回答:

// src/middleware.ts
import { createGuardMiddleware } from '@astroscope/node/guards';
import { sequence } from 'astro:middleware';
import { admin, authenticated } from './guards';
import { sessionMiddleware } from './session';

export const onRequest = sequence(
  sessionMiddleware,
  createGuardMiddleware([
    { match: [{ prefix: '/app' }], guards: [authenticated] },
    { match: [{ prefix: '/admin' }], guards: [admin] },
  ]),
);

模式是排除式词汇(prefix, (中文(简体) ), exact, (中文(简体) ), suffix, (中文(简体) ), includes, (中文(简体) ), pattern) (中文(简体) ). 这是深度防御,不是替代页面级呼叫:中间软件不能收缩 locals,所以区域内的页面仍然呼叫 guard(Astro, [...]) 用于输入的证明; 一个通过一次请求的警卫.

一个服务器岛通过Astro自己的端点,在页面路径的前缀规则之外:一个不能让每个人呼号的组件 guard(Astro, [...]) 在它自己的前题.

现有警卫

包运仅依赖请求的守护者; 取决于您会话形状的守护者(authenticated, (中文(简体) ), admin) 留在应用程序中,一个包裹将警卫送去,以为自己所关心的问题(captcha() 从 @astroscope/cap/server) (中文(简体) ).

rateLimit({ max, window, key?, name? })

每个键的固定窗口,内存和每个进程: max- 在内部提出请求 window 继续通过,下一个被拒绝 TOO_MANY_REQUESTS (429)直到窗口结束. 密钥是默认客户端地址; key(ctx) 选择另一个主题( 用户 id 、 目标电子邮件) 或返回 undefined 免除请求。 每个过程意味着每个复制品.

将它放在清单中,所以一个需要花费钱的警卫拒绝洪水:

import { captcha } from '@astroscope/cap/server';
import { rateLimit } from '@astroscope/node/guards';

guards: [rateLimit({ max: 5, window: 60_000 }), captcha()],

排除图案

@astroscope/node/excludes 用于中间软件的共享排除式词汇。 匹配本身来自 @entwico/dash/match· ; ExcludePattern 是线段的可序列子集 StringPattern (单位:千美元)exact 编号 : prefix 编号 : suffix 编号 : includes 编号 : pattern) (中文(简体) ).

import { RECOMMENDED_EXCLUDES, shouldExclude, withExcluded } from '@astroscope/node/excludes';

// pre-defined sets: DEV_EXCLUDES (vite dev paths), ASTRO_STATIC_EXCLUDES (/_astro/, /_image, /_i18n/),
// STATIC_EXCLUDES (favicon, robots.txt, ...), RECOMMENDED_EXCLUDES (dev + astro internals)

// in your own middleware
if (shouldExclude(ctx, [...RECOMMENDED_EXCLUDES, { exact: '/health' }])) return next();

// or wrap a third-party middleware without built-in exclude support
export const onRequest = withExcluded(someExternalMiddleware(), RECOMMENDED_EXCLUDES);

对于热路径, 编辑集一次 createMatcher 从 @entwico/dash/match 而不是每个请求扫描.

岛屿预装

没有它,一个岛屿的JS负载作为一个链:浏览器取来组件模块,解析,发现其进口,取出这些等. 在生产中,适配器知道每个岛的块从岛旁边的建筑并发出预装标记,所以浏览器可以同时取出所有东西. 递延岛屿client:visible, (中文(简体) ), client:idle, (中文(简体) ), client:media)在水合之前就预装了.

始终在生产; islands: false 只禁用预加载.

预压缩静态服务

在构建时, 每个可压缩文件在 dist/client 获得最大质量 .br (第11条)和 .gz (gzip 9) 旁边所写的变体——不缩小文件的变体被跳过. 静态处理器应请求谈判 Accept-Encoding 并服务最好的变体 与原始的内容类型, content-encoding, (中文(简体) ), vary: accept-encoding 以及每个变种的母体(包括304个).

嵌入式建构扭矩

总是在, 没有配置 :

  • 安全部门改革源图 ——服务器捆绑获得可读堆栈痕迹的源图;客户捆绑保持未被映射,所以浏览器无法获取源

反应群岛的安全部门改革效应剥离 @astroscope/react。 。 。 .

图像处理

Astro的默认锐利服务使 /_image 任何可以驱动的点名端点,所以适配器不进行图像处理,除非你要求:

node({
  imageService: 'auto', // 'on' | 'off' | 'auto'
});
  • 'auto' (默认)——当天体配置设置时 image.service 除了Astro的默认锐, 否则关闭。 明确 sharpImageService() 需求 'on'
  • 'on' ——astro的默认锐利服务,不需要进一步配置
  • 'off' - 甚至从一个明确的 image.service

关闭是大声的:任何 astro:assets 使用量(<Image>, (中文(简体) ), <Picture>, (中文(简体) ), getImage()以示解释 /_image 请回答404.

选项

node({
  // boot lifecycle; false disables it. Skipped automatically when no boot file exists.
  boot: {
    entry: 'src/boot.ts', // default: src/boot.ts or src/boot/index.ts
    watch: true, // dev: restart the dev server on boot-dependency changes
  },

  // Kubernetes-style probes on a separate port. Enabled by default in
  // production (never active in dev); false disables.
  health: {
    host: '0.0.0.0', // falls back to HEALTH_HOST env, then 0.0.0.0 (kubelet probes hit the pod IP)
    port: 9090, // falls back to HEALTH_PORT env, then 9090
  },

  // CSRF protection (origin check for POST/PUT/PATCH/DELETE with exclusions).
  // Enabled by default; false keeps astro's built-in checkOrigin instead.
  csrf: {
    exclude: [{ exact: '/api/auth/backchannel-logout' }],
  },

  // request logging at the native handler. Enabled by default in production;
  // false disables it (the log proxy keeps working).
  logging: {
    exclude: [{ prefix: '/internal/' }], // replaces RECOMMENDED_EXCLUDES
    extended: false, // query (redacted per redactedQueryParams)/headers/client address (may capture sensitive data)
    dev: false, // also log requests in dev (astro narrates them already)
  },

  // platform telemetry. Enabled by default in production, off in dev; false disables.
  telemetry: {
    exclude: [{ prefix: '/internal/' }], // replaces RECOMMENDED_EXCLUDES
    prometheus: { host: '0.0.0.0', port: 9464 }, // false disables the reader
    dev: false, // start the SDK in dev too (once per process)
  },

  // island dependency preloading (production-only); false disables it
  islands: false,

  // on-demand image processing: 'auto' = on only when image.service is set
  // in the astro config (see the Image processing section)
  imageService: 'auto',

  // query parameters redacted in server spans and extended request logs; replaces
  // OTEL_REDACTED_QUERY_PARAMS (the signed-url credentials of the OpenTelemetry conventions)
  redactedQueryParams: [...OTEL_REDACTED_QUERY_PARAMS, 'code', 'token'],

  bodySizeLimit: 1024 * 1024, // request body limit in bytes: 413 when announced larger, cut off when chunked
  shutdownTimeout: 10_000, // ms to wait for in-flight requests on shutdown; also bounds onShutdown and the telemetry flush, each
  keepAliveTimeout: 120_000, // ms an idle keep-alive connection stays open; must exceed the reverse proxy's idle timeout
});

HTTPS (韩语)

已建成的服务器服务于平原HTTP——在生产中,TLS预计将在入侵时终止. 对于已建服务器的本地运行(例如需要安全源代码的认证流),设置 SERVER_CERT_PATH 财务报告和审定财务报表 SERVER_KEY_PATH 直接为HTTPS服务——与 @astrojs/node数字 :

SERVER_CERT_PATH=./cert/tls.crt
SERVER_KEY_PATH=./cert/tls.key

两者都必须设置——如果只有一个存在,启动失败. 由于env文件在服务器开始监听前加载,变量可能存在 .env (或指向的文件) CONFIG_PATH)代替外壳环境.

这只影响到已建服务器 。 dev 服务器是 Vite 的—— 配置 vite.server.https 内 astro.config (原始内容存档于2018-09-21). for HTTPS in dev.

环境变量

变量效果
HOST 编号 : PORT运行时覆盖收听地址
SERVER_CERT_PATH 编号 : SERVER_KEY_PATH用给定的证书/密钥服务 HTTPS (参见 HTTPS (韩语)(中文(简体) )
HEALTH_HOST 编号 : HEALTH_PORT覆盖健康调查地址(当没有设置选项时)
CONFIG_PATH启动时要加载的信封文件( 返回到 ./.env(中文(简体) )
OTEL_EXPORTER_PROMETHEUS_HOST 编号 : OTEL_EXPORTER_PROMETHEUS_PORT覆盖普罗米修斯阅读器地址
OTEL_SDK_DISABLED=true完全禁用遥测 SDK
标准 OTEL_*出口商/资源配置(例如:. OTEL_EXPORTER_OTLP_ENDPOINT, (中文(简体) ), OTEL_SERVICE_NAME(中文(简体) )
ASTROSCOPE_NODE_AUTOSTART=disabled不启动服务器而构建条目( 导出) startServer()(中文(简体) )

关闭序列

在签字/签字:

  1. 准备探测器开始故障, draining 已登录
  2. 服务器停止接受连接并等待到 shutdownTimeout 飞行请求
  3. 页:1 beforeOnShutdown 听者运行,然后 onShutdown,然后是 afterOnShutdown 听众——以 shutdownTimeout; 一个挂接相被记录并留下
  4. shutdown complete { drainMs } 已登录, 健康服务器停止, 遥测冲出( 输入方式相同) , 程序退出代码 0

许可证

麻省理工学院

版本与发布记录

@astroscope/node 共发布 21 个版本,首次发布于 2026/07/10;过去 12 个月发布了 21 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
5.0.1latest2026/11/034 天前
5.0.02026/11/034 天前
4.2.02026/11/025 天前
4.1.02026/10/1227 天前
4.0.02026/10/0929 天前
3.1.22026/09/231 个月前

关于 @astroscope/node 的常见问题

@astroscope/node 是什么?

对Astro来说,有观点的、对云友好的节点适配器:靴子生命周期、健康探测器、请求日志、遥测、CSRF和静态服务在服务器周围运行,作为普通代码。listen()

如何安装 @astroscope/node?

在项目目录运行 npm install @astroscope/node,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:vite(^8.0.0)、astro(^7.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@astroscope/node 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@astroscope/node 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@astroscope/node 可以商用吗?

@astroscope/node 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@astroscope/node 的下载量有多少?

根据 npm 官方下载统计,@astroscope/node 在 2026/10/07 – 2026/11/05 这 30 天内被下载 1,968 次,日均约 66 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@astroscope/node 还在维护吗?

最新版本 5.0.1 发布于 2026/11/03(4 天前);至今共发布 21 个版本,其中过去 12 个月发布了 21 个;首次发布于 2026/07/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。