Output Console:在标签页面板里观察页面的 console.log —— 无需 DevTools
DevTools 控制台用起来很好 —— 当它开着的时候。大多数时候它没开。更糟的是:DevTools 控制台显示你此刻正在用的每一个页面的日志。在那一片噪音的雪崩里捞出「我这个特定流程的日志」很困难。Output Console(自 v2.13.66)是标签页本身里的一个只读日志查看器 —— 你看到这个标签页的日志,限定到这个域名,像其他 JustZix 面板一样始终可用。
四种窗口类型 —— Output Console 处在哪里
| 类型 | 它做什么 | 读/写 |
|---|---|---|
| CSS pane | 实时 CSS 编辑器,通过 <style> 应用 | 写(CSS → 页面) |
| JS pane | 按需运行的 JS 脚本(▶ 按钮) | 写(JS → 页面) |
| JS Console | 带 Ctrl+Enter 求值 + ↑↓ 历史的 REPL | 写(JS → 页面)+ 读(求值结果) |
| Output Console | 只读日志查看器 | 只读 |
前三种类型对页面做点什么。Output Console 在倾听。页面(以及其他 JustZix 脚本)的每次 console.log/warn/error/info/debug 调用都作为一行彩色文字到达。此外 —— 一个专用的 window.JUSTZIX.log() 通道(自 v2.13.73;自 v2.13.76 为首选别名,品牌名,冲突风险微乎其微),它不转发到原生控制台,只到 Output Console —— 你的脚本可以记录日志而不污染 DevTools。
架构 —— 页面钩子 + 向 sink 广播
Output Console 分两步工作:
- 页面钩子(MAIN world) —— 通过
chrome.scripting.executeScript({world: 'MAIN', func: hookFn})注入(自 v2.13.74 起对 CSP 免疫)。它包装console.log/warn/error/info/debug,保留到原始函数的透传(DevTools 不丢任何东西),但每次调用还会做window.postMessage({source:'jz-output-console', kind:'console', level, text, t})。 - 向 sink 广播(ISOLATED world) —— JustZix 的 content script 监听
window.message,通过_outputConsoleSinksMap 把条目广播给所有当前已渲染的 Output Console 面板。每个面板把它的那一行加到自己的日志里(按实例的状态)。
此外还有 stringifyArg —— 一个类型感知的参数转换器:
- string/number/bool → 字面量
Error→.stack(完整堆栈跟踪,不只是消息)- 对象 →
JSON.stringify,带防循环保护(WeakSet,这样JSON.stringify(window)不会卡死) - 函数 → 哨兵值
[Function: name] - undefined → 字面量
undefined(不会消失在 JSON.stringify 里)
viewMode:[C+J] / [C] / [J] —— 两个通道,一个面板
自 v2.13.73 起 Output Console 在头部有一个循环 viewMode 按钮。三个状态:
| 模式 | 你看到什么 | 使用场景 |
|---|---|---|
[C+J](两者) | 一切 —— 页面控制台 + JustZix 脚本 | 默认 —— 最完整的视图 |
[C](仅控制台) | 只有页面的 console.* | 调试页面,不带你的日志 |
[J](仅 JustZix) | 只有 window.JUSTZIX.log/.warn/.error/.info/.debug(若未被占用则也含 JZ.log) | 你的动作,干净,没有噪音 |
实现:每行零 JS 开销。每个条目获得一个 jz-output-line-{kind} 类,模式在 pane 上加一个 jz-output-mode-{mode} 类。隐藏的 CSS 规则做剩下的事:
.jz-output-mode-standard .jz-output-line-jz { display: none; }
.jz-output-mode-jz .jz-output-line-console { display: none; }
/* .jz-output-mode-both 显示一切 */
按级别过滤 + 搜索 —— 高级用户功能
⚙ 按钮下方打开一个带 5 个复选框的弹出框:log / info / warn / error / debug。默认全部勾选除了 debug(默认关 —— 页面滥用 console.debug 来刷屏)。和 viewMode 一样的机制 —— jz-output-hide-{level} 类 + CSS 规则,零 JS 开销。
此外日志上方有一个 🔍 搜索开关。实时过滤,子串匹配,不区分大小写。Esc 清空它。按标签页持久化在 sessionStorage 里 —— 过滤/搜索能在刷新后存活。
// 在 JS Console 里输入:
for (let i = 0; i < 5; i++) console.log(`用户动作 ${i}`);
for (let i = 0; i < 5; i++) console.warn(`用户警告 ${i}`);
JUSTZIX.log('我脚本的日志');
// Output Console 会显示 11 行。
// 切到 [J] → 只剩 1 行(JUSTZIX.log)。
// 切到 [C] + 只过滤 "warn" → 5 行(console.warn)。
// 搜索 "用户 3" → 捕获「用户动作 3」+「用户警告 3」。
使用场景 1 —— 监控 dataLayer.push(调试 GTM)
经典的 GTM 问题:你想知道每个标签往 dataLayer 发了什么。DevTools 控制台 = 在几十条其他日志里挤过去。Output Console:
// JS 规则(在网站上自动运行):
const origPush = window.dataLayer.push;
window.dataLayer.push = function(event) {
JUSTZIX.log('[dataLayer]', JSON.stringify(event));
return origPush.call(this, event);
};
JUSTZIX.log('dataLayer 钩子已安装。');
处于 [J] 模式的 Output Console 只显示你的 JUSTZIX.log 行 —— 每个 GTM 标签 = 一行彩色文字。过滤「purchase」→ 只剩电商。过滤「ga4」→ 只剩 GA 事件。无需 F12、无需 Tag Assistant、无需 Network 面板。
使用场景 2 —— 监控一个漫长的 QA 流程
一名 QA 测试员记录一个 30 分钟的流程。DevTools 控制台 5 分钟后就满了(默认上限约 1000 行)。Output Console:
- maxLines 2000(自 v2.13.73,之前是 500)—— 对长会话足够了。
- 按标签页的 sessionStorage —— 刷新不会清空日志(只有关标签页才会)。
- 自动滚动开关在头部 —— 关掉它以停在某一行;往回滚不会在每条新日志时跳到底部。
- Clear 按钮带可定制的
runColor(自 v2.13.71)—— 在下一个 QA 步骤前清空日志。
使用场景 3 —— 追踪异步错误
JS pane 的错误浮层(红色横条)不捕获异步错误 —— setTimeout(() => { throw err }, 100) 不会出现在 pane 里。Output Console 会捕获它们 —— 因为全局错误处理器也会调用 console.error:
// JS 规则:
window.addEventListener('error', (e) => {
JUSTZIX.error('[unhandled]', e.message, '@', e.filename + ':' + e.lineno);
});
window.addEventListener('unhandledrejection', (e) => {
JUSTZIX.error('[promise reject]', e.reason);
});
处于 [J] 模式 + 过滤「仅 error」的 Output Console —— 每个全局错误都在一个可读的列表里。当一个 SPA 每分钟记录 50 个错误而你只想要你自己的那些时,很方便。
使用场景 4 —— API 响应监视器
一个页面有不出现在视图里的 fetch(后台同步)。检查服务器响应了什么:
// JS 规则 —— 代理 fetch:
const origFetch = window.fetch;
window.fetch = async function(...args) {
const res = await origFetch.apply(this, args);
const clone = res.clone();
clone.json().then(data => {
JUSTZIX.log('[fetch]', args[0], '→', JSON.stringify(data).slice(0, 200));
}).catch(() => {});
return res;
};
Output Console 显示 URL + JSON 响应的前 200 个字符。按 URL 搜索 → 你看到单个端点。非常适合在没有 F12 Network 面板的情况下调试不稳定的 fetch。
有严格 CSP 的页面 —— 为什么内联脚本会失败(v2.13.74 修复)
在 v2.13.73 之前,页面钩子是作为带 textContent 的 <script> 元素注入的。它在约 99% 的页面上有效 —— 但严格的 CSP(script-src 'self' 不带 'unsafe-inline',例如 GitHub、Stripe 结账、银行)会静默地阻止执行。appendChild 成功(DOM 变更 OK),但脚本没被执行,也不抛错。
症状:window.JUSTZIX.log is not a function + console.log 不出现在 Output Console 里。修复(v2.13.74):钩子改用 chrome.scripting.executeScript({world: 'MAIN', func: hookFn}) —— 扩展的权限胜过页面的 CSP。首次安装后 Output Console 会收到一条欢迎消息(自 v2.13.76 起列出激活的别名):[JustZix] Output Console hook ready. API: window.JUSTZIX (or JZ / __JUSTZIX__).log/.warn/.error/.info/.debug。
坑
- 只读。你不能在这里打
2+2然后得到4。它是一个流视图,不是 REPL。要 REPL 就用 JS Console。 - 过滤里 console.debug 默认是关的。第一次你不会看到 debug 日志 —— 这是故意的(debug 刷屏是生产力杀手)。需要的话在 ⚙ 弹出框里开启它。
- 页面钩子必须尽早发生。钩子在某个 Output Console 面板首次渲染时注入。那个时刻之前的日志会丢失。最佳实践:把面板挂到一个带 URL 匹配的父规则上 —— 这样钩子从页面加载起就安装好了。
- 日志器总是可用,即便页面占用了 window.JZ。自 v2.13.76 起首选别名是
window.JUSTZIX(品牌名,冲突风险微乎其微),加上window.__JUSTZIX__始终被设置。更短的window.JZ只在空闲时才是别名 —— 与页面冲突时(例如 Google Ads)它留给页面。不确定域名时就用JUSTZIX.log()。 - 2000 行上限。更长的流 → 更老的行被挤出(FIFO)。通过 Clear 按钮把日志存到文件(JSON 导出计划在 v2.13.75;目前先从 DOM 复制粘贴)。
接下来做什么
Output Console 收尾了标签页里的迷你 IDE —— 一个只读通道,挨着三个写通道(CSS pane / JS pane / JS Console)。合在一起就是一个「应付 80% 场景的 Chrome DevTools 替代品」—— 无需 F12,按域名限定,UI 可定制。另见 window.JZ 辅助函数,了解专用日志通道,以及 调试 GTM dataLayer.push,作为具体应用。
安装 JustZix —— 完全免费,无需账号,没有服务器。
为这篇文章评分
暂无评分 — 成为第一个。