# @astroscope/node 中文文档

规范地址：https://npmcn.com/package/%40astroscope/node/

版本：5\.0\.1
npm 元数据更新时间：2026-11-03T15:16:13.009Z
中文译文更新时间：2026-11-07T09:08:01.709Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40astroscope/node
原文对照：https://npmcn.com/package/%40astroscope/node/?lang=original
项目主页：https://github.com/entwico/astroscope/tree/main/packages/node#readme
源码仓库：https://github.com/entwico/astroscope

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：575 kB，116 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：11 个
- peer 依赖：vite ^8\.0\.0，astro ^7\.0\.0
- 首次发布：2026-07-10T07:28:24.337Z
- 最新版本发布：2026-11-03T15:16:12.489Z
- 近 30 天下载量：1968（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：21（近 12 个月 21 个）

## 中文简介

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

## 安装

```sh
npm install @astroscope/node
```

也可以使用：`pnpm add @astroscope/node`、`yarn add @astroscope/node`、`bun add @astroscope/node`

## README

# @ 天文台/ 节点

对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)[岛屿预装](https://npmcn.com/package/%40astroscope/node/#readme-island-preloading)(中文(简体) )
-   **预压缩静态服务** ——建设时brotli/gzip变体,按 `Accept-Encoding`
-   **原生山顶** - http-native处理器(`oidc-provider`, ACME)安装在适配器的服务器上
-   **构建微调** ——安全部门改革源图
-   **图像处理关闭, 除非配置** - 没有明确 `image.service`,任意 `astro:assets` 使用大出声失败, 而不是打开 astro 的点名尖端([图像处理](https://npmcn.com/package/%40astroscope/node/#readme-image-processing)(中文(简体) )
-   **Dev 重新启动机械** —— 启动文件或条目接合的更改, 在控件页后重新启动 dev 服务器
-   **德夫岛暖和** —— 说 `.astro` 扫描源 `client:*` 组件; 它们的分解预优化, 它们的模块图在服务器启动时被取暖, 防止了 Vite 懒惰的分解发现的"504 过期优化 Dep"水分失败
-   **HTTPS 促进发展** —— 说 `SERVER_CERT_PATH` 编号 : `SERVER_KEY_PATH` 直接为已建服务器的本地运行服务 TLS ()[HTTPS (韩语)](https://npmcn.com/package/%40astroscope/node/#readme-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)[图像处理](https://npmcn.com/package/%40astroscope/node/#readme-image-processing)) (中文(简体) ).
-   **将请求机构限制为1个小米B** ——包含每个请求的Astro手柄,页面和端点,不仅仅是Astro所做的动作. 需要上传路径 `bodySizeLimit` (不涵盖本土山地).
-   **独立而已.** 没有中间软件模式——适配器总是拥有服务器.
-   **没有会话驱动程序 .** Astro 会话不支持, 除非您配置 `session.driver` 你自己来.
-   **没有健康探测器.** 健康服务器只存在于生产和 `astro preview`。 。 。 .

## 使用量

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

export default defineConfig({
  output: 'server',
  adapter: node(),
});
```

```typescript
// 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模式而无需让消费者通过线程来通过:

```typescript
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` 抛出.

```typescript
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中,启动门会随着出错而使持有页面保持上行.

```typescript
// 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服务器重启.

```typescript
// 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`,所以选项可以安全读取配置.

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

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

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

```typescript
// 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`在外边,他们去 根伐木机.

```typescript
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` 让中间软件报告它实际服务的内容:

```typescript
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`](https://npmcn.com/package/%40astroscope/react/README.md), (中文(简体) ), [`@astroscope/wormhole`](https://npmcn.com/package/%40astroscope/wormhole/README.md), (中文(简体) ), [`@astroscope/i18n`](https://npmcn.com/package/%40astroscope/i18n/README.md)

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

## 健康检查

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

```typescript
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挑战处理器——将其挂入适配器的服务器上,而不是在天体中间软件内装出节点对象:

```typescript
// 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`) (中文(简体) ).

```typescript
// 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` 提示规则强制导入). 保护人员在输入验证后运行;他们所申报的字段被合并到计划中,并在操作者面前再次剥离:

```typescript
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或成形体:

```typescript
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 }),
});
```

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

```astro
---
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` 处理者.

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

```typescript
// 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` 免除请求。 每个过程意味着每个复制品.

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

```typescript
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`](https://github.com/entwico/dash)· ; `ExcludePattern` 是线段的可序列子集 `StringPattern` (单位:千美元)`exact` 编号 : `prefix` 编号 : `suffix` 编号 : `includes` 编号 : `pattern`) (中文(简体) ).

```typescript
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`](https://npmcn.com/package/%40astroscope/react)。 。 。 .

## 图像处理

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

```typescript
node({
  imageService: 'auto', // 'on' | 'off' | 'auto'
});
```

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

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

## 选项

```typescript
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`数字 :

```sh
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 (韩语)](https://npmcn.com/package/%40astroscope/node/#readme-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 是什么？

对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 和提交记录判断。

