跳转到内容

logging

logging 用来控制 createDocsIslands() 产生的包内日志,以及这个包公开暴露的 logger helper。它不会改变渲染逻辑,只决定 @docs-islands/* 在 Node 和浏览器里哪些消息可见。

每个 createDocsIslands() 实例都会持有隔离的 logger scope。VitePress 会把这个 scope 注入到构建图中,通用的 @docs-islands/logger runtime 会在没有显式 scope 时读取它,所以并行的多个 VitePress 实例或测试不会互相覆盖 logging 配置。框架无关的直接 logger 用法请使用 @docs-islands/logger

什么时候用它

当集成本身正常、但终端或浏览器控制台太吵时,可以用 logging 收窄输出范围,尤其适合按 docs-islands 内部子系统聚焦日志。接入初期通常只保留 warnerror;排查问题时,可以打开 debug,查看是哪几条规则放行了当前日志,以及 logger 已运行的相对耗时。

最小示例

.vitepress/config.ts
ts
import { createDocsIslands } from '@docs-islands/vitepress';
import { react } from '@docs-islands/vitepress/adapters/react';
import { hmr } from '@docs-islands/vitepress/logger/presets';

const islands = createDocsIslands({
  adapters: [react()],
  logging: {
    levels: ['warn', 'error'],
    plugins: { hmr },
    rules: {
      'hmr/markdownUpdate': 'off',
      'hmr/viteAfterUpdate': {},
    },
  },
});

islands.apply(vitepressConfig);

这个配置只保留选中的 docs-islands HMR 日志的 warnerrorhmr/viteAfterUpdate 使用预设默认匹配器,hmr/markdownUpdate 则被显式关闭。'off'{ enabled: false } 的简写。

判断模型

当没有配置 logging.rules 时,logger 使用默认可见级别:

  • debug: false:输出 errorwarninfosuccess
  • debug: true:输出 errorwarninfosuccessdebug

当配置了 logging.rules 时,logger 会先展开 plugin 规则,再进入规则模式:

  1. 先过滤掉 enabled: false 的 rule。它们不参与 scope 匹配、不参与 level 放行,也不会出现在 debug label 中。
  2. 每一条 active rule 都会按日志的 maingroupmessage 做匹配。只要 rule 声明了多个字段,这些字段就必须同时命中。
  3. 命中的 rule 使用 rule.levels ?? logging.levels 作为自己的 effective levels。若两者都没写,则使用默认非 debug 级别集合。
  4. 只要有任意一条命中的 active rule 放行当前 level,日志就会输出。
  5. 如果处于规则模式但没有 active rule 命中,则不输出;不会 fallback 到根 levels

多条 rule 可以同时放行同一条日志。它们的可见级别按并集生效,debug label 按 logging.rules 中的声明顺序展示。

根配置项

配置项含义
debug启用诊断输出。可见的 errorwarninfosuccess 日志会带上命中的 label,以及 12.34ms 这样的相对耗时后缀。
levels根可见级别集合。在规则模式下,它是没有声明 rule.levels 的 rule 的默认 effective levels;它不是用来强制收窄所有 rule 的上限。
plugins可选的预设 plugin 注册表。对象 key 会成为 logging.rules["<plugin>/<rule>"] 里的命名空间。
rules既支持原始规则数组,也支持 plugin 规则对象。它存在且规范化后非空时,日志是否输出只由 active 且命中的 rules 决定。

Plugin 规则

如果你只是想过滤 docs-islands 内部日志,推荐优先使用 logging.plugins

ts
import { hmr, runtime } from '@docs-islands/vitepress/logger/presets';

const logging = {
  debug: true,
  levels: ['warn'],
  plugins: { hmr, runtime },
  rules: {
    'hmr/viteAfterUpdate': {},
    'runtime/reactDevRender': {
      levels: ['warn', 'error'],
    },
    'runtime/renderValidation': 'off',
  },
};
  • plugins 用来注册 logging 预设 plugin,例如 hmr
  • rules["<plugin>/<rule>"] = {} 表示启用该预设规则并使用默认匹配器。
  • rules["<plugin>/<rule>"] = 'off' 表示关闭该预设规则,等价于 { enabled: false }
  • override 对象只允许覆盖 enabledmessagelevelsgroupmain 始终继承 preset matcher。

内建日志预设与覆盖范围

@docs-islands/vitepress/logger/presets 导出的 preset,本质上是一组内建日志的默认 main/group 匹配器。下面这张目录会列出所有 preset、所有 rule,以及它们默认约束到的范围。

Preset 总览

内建 logging preset 与 rule 目录

可以把 preset 理解成按子系统打包好的 matcher 集合,而 rule 则对应到一条具体的内建日志流。

9 个 preset · 33 条 rule

下面这份目录直接按当前导出的 preset 定义展开。你可以点击任意 preset 名、rule 名或 main/group matcher 直接复制。你会先看到一张 preset 总表,随后每个分组表会继续展开对应 rule 的主要作用、约束范围,以及默认的 main/group matcher。

Preset

Preset 总表

Preset主要作用约束范围规则数
构建阶段里与 framework bundling、SSR 产物以及最终集成收尾相关的日志。覆盖 browser bundle、SSR bundle、MPA 集成、shared client runtime metafile,以及最终 HTML 处理这类 VitePress 侧 build 分组。7 条 rule
功能流水线正式开始之前的配置解析与环境前置检查日志。当前只覆盖 VitePress 侧的 Node 版本校验流程。1 条 rule
开发阶段里 Markdown 容器热更新和 React runtime 后续处理相关的日志。覆盖 Markdown HMR 重解析、React runtime 预备、SSR-only 重渲染,以及 Vite 更新后的渲染阶段。5 条 rule
Markdown 页面、框架脚本块以及 React 引用分析相关的解析日志。覆盖页面结构扫描、脚本块发现,以及 React import / 组件引用解析这两类 parser 分组。2 条 rule
VitePress 插件层里,把渲染策略接入站点的那部分日志。当前只覆盖 rendering-strategy plugin 在 VitePress 侧的运行流程。1 条 rule
从 VitePress 上下文派生页面或模块引用时的解析日志。当前只覆盖 inline page 解析流程。1 条 rule
浏览器端加载、渲染编排,以及部分共享 core 运行时校验相关的日志。同时覆盖 VitePress 侧 runtime 分组,以及 core 侧的运行时校验 / React manager 分组。11 条 rule
Site DevTools 的 AI 服务与 build report 相关日志。覆盖 VitePress 侧 Site DevTools AI server 与 AI build report 分组。2 条 rule
core 侧 Markdown 转换与 SSR 集成相关的 transform 日志。覆盖 Markdown 组件标签转换、SSR 容器集成,以及 SSR CSS 注入这三类 core transform 分组。3 条 rule

Rule 明细

7 条 rule

覆盖 browser bundle、SSR bundle、MPA 集成、shared client runtime metafile,以及最终 HTML 处理这类 VitePress 侧 build 分组。

main
Rule主要作用maingroup
用于跟踪 Browser 侧 framework bundle 的生成和产物组织。
用于跟踪构建末尾的结果整理与收尾阶段。
用于跟踪 MPA 模式下的 framework integration 流程。
用于跟踪共享 client runtime 的 metafile 收集与分析。
用于跟踪 SSR bundle 的生成和产物布局。
用于跟踪 SSR 集成产物的接线与构建处理。
用于跟踪最终 HTML 注入、改写与框架产物落位。

Rule 明细

1 条 rule

当前只覆盖 VitePress 侧的 Node 版本校验流程。

main
Rule主要作用maingroup
用于跟踪 Node 版本检查与相关环境 guardrail。

Rule 明细

5 条 rule

覆盖 Markdown HMR 重解析、React runtime 预备、SSR-only 重渲染,以及 Vite 更新后的渲染阶段。

main
Rule主要作用maingroup
用于跟踪 Markdown 文件改动后,对容器脚本重新解析的流程。
用于跟踪 HMR 继续推进前的 React runtime 预备工作。
用于跟踪开发期更新后 ssr:only 容器的重渲染。
用于跟踪 Vite 完成更新后 docs-islands 的后续处理。
用于跟踪 Vite 更新处理完成后的渲染阶段。

Rule 明细

2 条 rule

覆盖页面结构扫描、脚本块发现,以及 React import / 组件引用解析这两类 parser 分组。

main
Rule主要作用maingroup
用于跟踪框架无关的页面解析与脚本块发现。
用于跟踪 React 专属的 import 解析、组件绑定与引用校验。

Rule 明细

1 条 rule

当前只覆盖 rendering-strategy plugin 在 VitePress 侧的运行流程。

main
Rule主要作用maingroup
用于跟踪渲染策略插件的挂载与运行状态。

Rule 明细

1 条 rule

当前只覆盖 inline page 解析流程。

main
Rule主要作用maingroup
用于跟踪 inline page 的定位与解析决策。

Rule 明细

11 条 rule

同时覆盖 VitePress 侧 runtime 分组,以及 core 侧的运行时校验 / React manager 分组。

mainmain
Rule主要作用maingroup
用于跟踪 core 层 React component manager 的生命周期。
用于跟踪 core 层 React render strategy 的解析流程。
用于跟踪运行时 CSS 预加载与加载状态管理。
用于跟踪浏览器端 React client 入口模块的加载。
用于跟踪 VitePress 层 React component manager 的生命周期。
用于跟踪开发期内容更新落地后的运行时响应。
用于跟踪开发期挂载流程走向 fallback 分支时的状态。
用于跟踪开发期挂载阶段采用的渲染分支。
用于跟踪开发期 React 渲染执行流程。
用于跟踪开发期 runtime loader 的启动过程。
用于跟踪 core 层对渲染结果的校验。

Rule 明细

2 条 rule

覆盖 VitePress 侧 Site DevTools AI server 与 AI build report 分组。

main
Rule主要作用maingroup
用于跟踪 AI build report 的生成、缓存与读取。
用于跟踪 Site DevTools AI server 请求与服务端集成状态。

Rule 明细

3 条 rule

覆盖 Markdown 组件标签转换、SSR 容器集成,以及 SSR CSS 注入这三类 core transform 分组。

main
Rule主要作用maingroup
用于跟踪运行时产物输出前的 Markdown 组件标签转换。
用于跟踪 SSR 容器与页面输出的整合过程。
用于跟踪 SSR 相关 transform 阶段的 CSS 注入处理。

公开 Logger 用法

@docs-islands/vitepress/logger 是 VitePress logger facade。它只暴露 createLoggerformatDebugMessage;通用的直接 runtime 配置能力位于 @docs-islands/logger

logging 定义的是 logger 的运行时可见性策略。它决定日志在运行时是否输出;在 debug 模式下,也会决定可见日志附带哪些规则标签和相对耗时信息。

@docs-islands/logger 保持 framework-agnostic。docs-islands 内部通过 @docs-islands/utils/logger 把 bundler 注入的 __DOCS_ISLANDS_LOGGER_SCOPE_ID__ 显式桥接给底层 logger,而 @docs-islands/vitepress/logger.createLogger(...) 只有在该注入 scope 存在时才可用。

Runtime Policy 与 Build-Time Optimization

logger tree-shaking plugin 是一个编译期优化层。它会在构建阶段复用已经解析好的 logging 规则,对静态可判定的 logger 调用做裁剪。

这两层相关,但不是同一个概念:

  • logging 始终定义运行时行为。
  • tree-shaking plugin 只处理它能安全静态证明的子集。
  • 无法静态分析的日志会继续保留在产物中,并交给 runtime logger 决定是否输出。

所以,“运行时会被 suppress” 不等于 “一定会被编译期删除”。

维度logginglogger tree-shaking plugin
生效阶段运行时编译期
是否决定最终控制台输出否,runtime 语义仍然是基准
是否移除 bundle 中的静态文案是,但仅限受支持的静态子集
是否复用已解析的 logging 规则
覆盖范围完整运行时模型静态可判定子集
无法分析时的退化行为正常运行时匹配保留调用并交给 runtime
.vitepress/config.ts
ts
import { createDocsIslands } from '@docs-islands/vitepress';
import { createLogger } from '@docs-islands/vitepress/logger';

const logger = createLogger({
  main: '@acme/custom-docs',
}).getLoggerByGroup('userland.metrics');
const hiddenLogger = createLogger({
  main: '@acme/custom-docs',
}).getLoggerByGroup('userland.hidden');

const islands = createDocsIslands({
  logging: {
    debug: true,
    rules: [
      {
        label: 'userland-metrics',
        main: '@acme/custom-docs',
        group: 'userland.metrics',
        levels: ['info'],
      },
    ],
  },
});

islands.apply(vitepressConfig);

logger.info('visible userland info');
hiddenLogger.info('suppressed userland info');

在这个配置下,userland.metrics 会保留输出,而 userland.hidden 会被抑制。

Logger Tree-Shaking Plugin

createDocsIslands() 管理的构建链里,docs-islands 已经会自动安装 logger tree-shaking transform。

如果你只是想在 VitePress 站点里使用公开 logger,同时又希望拿到生产环境裁剪能力,可以显式安装公开 plugin:

.vitepress/config.ts
ts
import { defineConfig } from 'vitepress';
import { loggerTreeShaking } from '@docs-islands/logger/plugin';

export default defineConfig({
  vite: {
    plugins: [
      loggerTreeShaking.vite({
        logging: {
          levels: ['warn', 'error'],
        },
      }),
    ],
  },
});

如果省略 logging,plugin 会回退到默认 logger 可见性策略,这仍然会裁剪静态可判定的 debug 日志。如果你还希望 createDocsIslands() 模块图之外的动态日志也遵循同一套策略,则需要额外配置 runtime logger。

生产环境 Tree-Shaking

当 tree-shaking transform 生效时,只要某条用户静态日志能够被证明会被已解析的 logging 规则抑制,这条日志语句就会从生成的 JavaScript 中移除,因此它的静态 message 文案也不会进入最终 bundle。

如果你希望获得 pruning coverage,推荐使用下面这种直接写法:

ts
import { createLogger } from '@docs-islands/vitepress/logger';

const logger = createLogger({
  main: '@acme/custom-docs',
}).getLoggerByGroup('userland.metrics');

logger.info('static metric ready');
logger.success('static metric uploaded');
logger.warn('static metric delayed');
logger.error('static metric failed');
logger.debug('static metric details');

优化器只分析这个受约束的静态形态:

  • createLogger 必须是从 @docs-islands/vitepress/logger 命名导入的函数。
  • maingetLoggerByGroup(...) 和日志 message 都必须是字符串字面量。
  • 日志调用必须是独立语句,例如 logger.info('message')
形态是否参与 pruning
const logger = createLogger({ main: 'x' }).getLoggerByGroup('y')
logger.info('msg') / warn / error / success / debug
模板字符串、字符串拼接、变量 message、动态 main、动态 group
alias、destructuring、reassignment、动态 method 访问
const result = logger.info('msg') 这类非独立表达式

动态日志仍然可用,但会刻意保留给运行时过滤:

ts
logger.info(`metric ${name}`);
logger.info(`metric ${name}`);
logger.info(message);
createLogger({ main }).getLoggerByGroup(group).info('dynamic binding');

这些写法依然兼容可运行,但 docs-islands 不保证它们的 message 文案会从生产产物中消失。pruning coverage 只是 runtime logging coverage 的静态可判定子集,不是它的替代品。

通用 Logger 用法

如果需要在 VitePress 管理的构建链之外直接使用 logger,请从框架无关的包导入:

ts
import { createLogger, setLoggerConfig } from '@docs-islands/logger';

setLoggerConfig({
  levels: ['warn', 'error'],
});

const logger = createLogger({
  main: '@acme/custom-docs',
}).getLoggerByGroup('userland.metrics');

logger.warn('visible generic warning');

不要再把 @docs-islands/vitepress/logger 当作通用 logger 入口使用。它只服务于 createDocsIslands() 建立的 VitePress 构建模块图。

交互式 Scope Probe

下面这个 playground 会直接在当前 docs 站里运行 VitePress logger facade:

  • 正常的 @docs-islands/vitepress/logger 导入会通过 runtime 注入使用当前 createDocsIslands() 实例的 logger scope。
  • 框架无关的 @docs-islands/logger runtime 演示已经放在独立 logger 包页面中。
Scope 验证

Logger scope playground

VitePress 导入会从 runtime 注入读取当前 docs-islands logger scope,并遵循当前 createDocsIslands({ logging }) 策略。

这个 playground 会在页面里实际运行一组 VitePress logger probe,并把对应的 console 输出回填到组件 UI,用来直接验证注入 logger scope 的行为。

Scope 验证正在运行探针...

注入 scope 导入

这个卡片使用 docs-islands 构建图中的 VitePress logger 导入。logger runtime 会读取 createDocsIslands() 注入的 scope,不再暴露通用 runtime 配置能力。

导入路径
状态
正在运行探针...
setLoggerConfig(...) 行为
由 createDocsIslands({ logging }) 管理
可见消息是否输出
隐藏消息是否输出
捕获到的 warning
捕获到的 console 输出

复用内建 main/group 的影响

如果你的自定义日志故意或无意复用了 docs-islands 内建日志使用的 main / group,那么它们也可能命中同一批 preset rule 或原始 logging.rules

  • 你的用户日志会跟着内建日志一起被放行或一起被抑制。
  • debug 模式下,它们可能带上和内建日志相同的 rule label,增加排查歧义。
  • 后续为了过滤内建日志而调整 preset / rule 时,也可能连带影响用户日志。

除非你就是希望用户日志和内建日志共用同一套过滤空间,否则更推荐使用独立的 maingroup 命名,例如 @acme/custom-docs + userland.*

原始 Rule 字段

当你需要写更底层的 group / message 匹配,而不是绑定到某个 preset label 时,依然可以继续使用数组形式的 logging.rules

字段含义
label必填、稳定的规则标识。开启 debug 后,可见日志会以 [LabelA][LabelB] 的形式展示真正贡献输出的规则。
enabled可选预过滤开关。false 表示这条 rule 完全不生效;它不是低优先级 deny rule。
main可选包名精确匹配,例如 @docs-islands/vitepressmain 不使用 glob。
group可选 logger group 匹配。普通字符串按精确匹配;包含 glob magic 时使用 picomatch,例如 runtime.react.*test.case.?1
message可选消息文本匹配。普通字符串按精确匹配;包含 glob magic 时使用 picomatch,例如 *timeout*request *task-[ab]
levels可选的当前 rule effective levels。它会替代根 levels,并和其它命中 rule 的 levels 一起组成并集。

匹配示例

原始规则数组仍然适合那种跨 preset 的宽匹配,比如直接按大范围 group 前缀或消息文本筛选。

ts
const islands = createDocsIslands({
  adapters: [react()],
  logging: {
    debug: true,
    levels: ['warn'],
    rules: [
      {
        label: 'react-runtime-warnings',
        main: '@docs-islands/vitepress',
        group: 'runtime.react.*',
      },
      {
        label: 'runtime-timeouts',
        group: 'runtime.*',
        message: '*timeout*',
        levels: ['error'],
      },
    ],
  },
});

来自 runtime.react.component-managerwarn 会由 react-runtime-warnings 放行。包含 timeouterror 会由 runtime-timeouts 放行。如果同一条日志同时命中两条 rule,并且当前 level 被它们放行,debug 模式会按声明顺序打印两个 label。

debug 输出示例:

bash
[react-runtime-warnings][runtime-timeouts] @docs-islands/vitepress[runtime.react.component-manager]: request timeout 12.34ms

常见模式

只保留 React 运行时的告警和错误

ts
const islands = createDocsIslands({
  adapters: [react()],
  logging: {
    levels: ['warn', 'error'],
    rules: [
      {
        label: 'react-runtime-warn-error',
        main: '@docs-islands/vitepress',
        group: 'runtime.react.*',
      },
    ],
  },
});

宽泛规则与具体 message 规则组合

ts
const islands = createDocsIslands({
  adapters: [react()],
  logging: {
    levels: ['warn'],
    rules: [
      {
        label: 'runtime-warnings',
        group: 'runtime.*',
      },
      {
        label: 'timeout-errors',
        message: '*timeout*',
        levels: ['error'],
      },
    ],
  },
});

这会保留 runtime 的 warning,同时额外保留任何包含 timeout 的 error。两条 rule 不会互相覆盖,而是一起贡献输出能力。

临时关闭一条 rule

ts
const islands = createDocsIslands({
  adapters: [react()],
  logging: {
    rules: [
      {
        label: 'runtime-react',
        group: 'runtime.react.*',
        levels: ['warn'],
      },
      {
        label: 'runtime-react-disabled',
        enabled: false,
        group: 'runtime.react.component-manager',
        levels: ['error'],
      },
    ],
  },
});

被禁用的 rule 会被完全忽略。它不会静音或覆盖 active 的 runtime-react rule,也不会污染 debug label。

按消息文本筛选

ts
const islands = createDocsIslands({
  adapters: [react()],
  logging: {
    rules: [
      {
        label: 'hydration-timeouts',
        message: '*hydration*timeout*',
        levels: ['warn', 'error'],
      },
    ],
  },
});

message 规则适合短时间排查问题,尤其是某个高频 group 里只有少数消息值得关注时。

根据 MIT 许可证发布。 (0826c60)

Global Debug Console

docs-islands Runtime Globals

Browse the runtime globals injected by @docs-islands/vitepress and inspect their current live values.

Console helper: window.__DOCS_ISLANDS_SITE_DEVTOOLS__.getGlobal('__PAGE_METAFILE__')

Injected Globals

VitePress runtime site data. Hidden in dev and MPA mode.