[{"data":1,"prerenderedAt":70},["ShallowReactive",2],{"case-dev-build-log-ws-mock-dsl-zh":3,"blog-list-zh":13},{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9,"series":10,"seriesOrder":11,"html":12},"dev-build-log-ws-mock-dsl","为什么我们重新设计了 WebSocket Mock DSL，而不是用 YAML、JSON 或 JS","轻量 WebSocket Mock 不该比 HTTP Mock 更重。YAML、JSON、JS 都能做，但写「连上、登录、心跳」太啰嗦。我们自研短 DSL，就是让轻量 Mock 更轻。","2026-08-13",false,"DevPeek 开发实录：为什么 WebSocket Mock 自研 Flow DSL。现成 YAML、JSON、JS 能做重活；轻量顺序剧本用更短的文本来写。","dev-build-log",3,"\u003Ch2>轻量 Mock，不该先变重\u003C\u002Fh2>\n\u003Cp>HTTP 联调里，\u003Ca href=\"\u002Fdocs\u002Fmock\u002F\">Mock\u003C\u002Fa> 很轻：抓一帧，勾特征，改响应。一来一回就结束。\u003C\u002Fp>\n\u003Cp>WebSocket 的\u003Cstrong>轻量\u003C\u002Fstrong>场景其实差不多短：连上、登录、回一句、隔几秒推个心跳。要 mock 的是一小段对话，不是一篇程序。\u003C\u002Fp>\n\u003Cp>现成方案却常把这段对话塞进 JSON 规则表、YAML 配置、或一段 JS。\u003Cstrong>功能很强，也能跑。\u003C\u002Fstrong> 问题是：本来十来行能说完的事，要先填字段、堆括号、写 \u003Ccode>setInterval\u003C\u002Fcode>。轻量 Mock 先被容器写重了。\u003C\u002Fp>\n\u003Cp>我们重新设计了一套 DSL，图的就是这件事——\u003Cstrong>让轻量 Mock 更轻\u003C\u002Fstrong>。界面叫 \u003Cstrong>WS Flow\u003C\u002Fstrong>，文件是 \u003Ccode>.dpws\u003C\u002Fcode>。人写剧本；JSON 只当编译产物。\u003C\u002Fp>\n\u003Ch2>同一段对话\u003C\u002Fh2>\n\u003Cp>「连上 challenge → 登录成功 → 每 15 秒 tick」，规则 JSON 常见是这样：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  &quot;url&quot;: &quot;wss:\u002F\u002Fapi.example.com\u002Fws&quot;,\n  &quot;onOpen&quot;: [{ &quot;send&quot;: { &quot;type&quot;: &quot;challenge&quot; } }],\n  &quot;handlers&quot;: [\n    {\n      &quot;match&quot;: { &quot;type&quot;: &quot;login&quot; },\n      &quot;reply&quot;: { &quot;type&quot;: &quot;loginSuccess&quot; },\n      &quot;then&quot;: {\n        &quot;every&quot;: &quot;15s&quot;,\n        &quot;send&quot;: { &quot;type&quot;: &quot;tick&quot; }\n      }\n    }\n  ]\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>字花在 \u003Ccode>onOpen\u003C\u002Fcode>、\u003Ccode>handlers\u003C\u002Fcode>、\u003Ccode>match\u003C\u002Fcode>、\u003Ccode>reply\u003C\u002Fcode>、\u003Ccode>then\u003C\u002Fcode> 上。YAML 少了括号，壳还在：键、列表、再套一层，缩进既像配置又像对话。JS 最能打，一段 Mock 也容易变成小程序。\u003C\u002Fp>\n\u003Cp>同一段，Flow 是这样：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-text\"># ws wss:\u002F\u002Fapi.example.com\u002Fws\n# profile type\n# ping auto\n\n--@open\n    challenge\n\n--login\n    loginSuccess\n        --@loop 15s\n            tick\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>\u003Ccode>--@open\u003C\u002Fcode> 是连上，\u003Ccode>--login\u003C\u002Fcode> 是客户端登录，缩进里的是回什么、之后怎么推。\u003Ccode>loginSuccess\u003C\u002Fcode> 按文件头编成 \u003Ccode>{&quot;type&quot;:&quot;loginSuccess&quot;}\u003C\u002Fcode>，业务帧不必每次手写 JSON。延迟、周期推送写在行上（\u003Ccode>+300ms\u003C\u002Fcode>、\u003Ccode>--@loop 15s\u003C\u002Fcode>），不必另起控制流。\u003C\u002Fp>\n\u003Cp>语法就这些：缩进树，加少量符号（\u003Ccode>--\u003C\u002Fcode>、\u003Ccode>--@\u003C\u002Fcode>、\u003Ccode>~scope\u003C\u002Fcode>、\u003Ccode>|\u003C\u002Fcode>、\u003Ccode>$\u003C\u002Fcode>、\u003Ccode>+delay\u003C\u002Fcode>、\u003Ccode>!close\u003C\u002Fcode>）。没有 if\u002Ffor\u002F函数。场景见 \u003Ca href=\"\u002Fdocs\u002Fwsmock-dsl\u002F\">WebSocket Mock\u003C\u002Fa>，符号见 \u003Ca href=\"\u002Fdocs\u002Fdpws\u002F\">\u003Ccode>.dpws\u003C\u002Fcode> 语言参考\u003C\u002Fa>。\u003C\u002Fp>\n\u003Cp>HTTP Mock 仍从抓包、GUI 走；WS Flow 只服务这种短对话。两条不要揉成一张表。\u003C\u002Fp>\n\u003Ch2>轻的用 DSL，重的仍用 JS\u003C\u002Fh2>\n\u003Cp>Flow \u003Cstrong>只对准轻量 Mock\u003C\u002Fstrong>：顺序的一小段会话。并发乱序、深分支、动态或随机 payload、要读外部数据——YAML\u002FJSON 的生态（Schema、diff、CI）或直接写 JS 更合适。那不是 DSL 没写完，是我们不想把轻量语法撑成通用语言。\u003C\u002Fp>\n\u003Cp>自研也有账：解析器、报错、高亮、补全都要自己养，同事要学新符号。校验已经接到编辑器，高亮和补全还早。换来的是：打开文件就像在读对话，而不是在读配置。\u003C\u002Fp>\n\u003Ch2>和前两篇是同一条线\u003C\u002Fh2>\n\u003Cp>\u003Ca href=\"\u002Fblog\u002Fdev-build-log-sqljs-to-better-sqlite3\u002F\">抓包历史从 sql.js 迁到原生 SQLite\u003C\u002Fa>，解决的是挂久了的存储。\u003Cbr>\u003Ca href=\"\u002Fblog\u002Fdev-build-log-electron-to-tauri\u002F\">桌面壳从 Electron 换成 Tauri\u003C\u002Fa>，解决的是壳太重。\u003Cbr>这篇是：轻量长连接 Mock 不该先被 JSON\u002FYAML\u002FJS 写重。我们用更短的 DSL，让它保持轻。\u003C\u002Fp>\n\u003Ch2>相关文档\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"\u002Fdocs\u002Fwsmock-dsl\u002F\">WebSocket Mock\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fdocs\u002Fdpws\u002F\">\u003Ccode>.dpws\u003C\u002Fcode> 语言参考\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fdocs\u002Fmock\u002F\">Mock 规则\u003C\u002Fa>\u003C\u002Fli>\n\u003Cli>\u003Ca href=\"\u002Fdocs\u002Fcapture\u002F\">抓包与过滤\u003C\u002Fa>\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Chr>\n\u003Cp>欢迎 \u003Ca href=\"\u002F\">下载 DevPeek\u003C\u002Fa> 看 HTTP Mock 与抓包怎么串；WS Flow 以 \u003Ca href=\"\u002Fdocs\u002Fwsmock-dsl\u002F\">WebSocket Mock 文档\u003C\u002Fa> 为准。不同看法可以到 \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FGYPengDev\u002Fdevpeek\u002Fdiscussions\">GitHub Discussions\u003C\u002Fa> 聊。\u003C\u002Fp>\n",{"items":14},[15,16,23,30,37,43,51,57,64],{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9,"series":10,"seriesOrder":11},{"slug":17,"title":18,"summary":19,"date":20,"featured":8,"seoDescription":21,"series":10,"seriesOrder":22},"dev-build-log-electron-to-tauri","DevPeek 架构改造：抛弃 Electron，拥抱 Tauri","联调工具不该为「开一个窗口」再拖一整套 Chromium。我们把业务收到 Core，桌面壳换成 Tauri，安装更轻、后台更省，关窗后托盘里也能随时唤回来。","2026-08-08","DevPeek 开发实录：桌面壳从 Electron 迁到 Tauri，业务留在 Core，壳只负责窗口与系统能力，体积与资源占用更友好。",2,{"slug":24,"title":25,"summary":26,"date":27,"featured":8,"seoDescription":28,"series":10,"seriesOrder":29},"dev-build-log-sqljs-to-better-sqlite3","抓包历史为什么从 sql.js 迁到原生 SQLite","早期 DevPeek 用纯 JavaScript 版 SQLite 存抓包记录，联调一忙就占内存、列表发紧。我们换成系统级原生 SQLite 后，代理可以连续挂一整天，内存也稳。","2026-08-05","DevPeek 开发实录：抓包历史存储从 sql.js 换成原生 SQLite，解决长时间联调内存上涨、列表卡顿，让代理可以挂一整天。",1,{"slug":31,"title":32,"summary":33,"date":34,"featured":8,"seoDescription":35,"series":36,"seriesOrder":22},"mock-map-route-split-api","API 已迁新服务，前端还没发版？用「转发规则」联调","服务拆分后，前端仍请求旧 API，订单接口却已经迁到新服务。使用 DevPeek「转发规则」无需修改前端代码，即可把指定接口转发到新域名；若新服务未完成，还可以用 Mock 先跑通页面。","2026-07-26","微服务联调与 API 域名迁移：用 DevPeek「转发规则」做 API 转发，不改前端即可把旧域名请求指到新服务；服务迁移未完成时可用 Mock 先验页面。附接口联调 Demo。","api-debug-new-tricks",{"slug":38,"title":39,"summary":40,"date":41,"featured":8,"seoDescription":42,"series":36,"seriesOrder":29},"api-param-encryption-debug","H5 接口参数加密？DevPeek 一键解密调试","联调时接口参数 AES 加密看不到明文？用 DevPeek 参数转换功能，填好密钥和 IV 就能自动解密，还能改参重放。","2026-07-18","用 DevPeek 参数转换功能解密 AES-GCM 加密的 H5 API 请求，支持双向转换、明文编辑、调试重放。",{"slug":44,"title":45,"summary":46,"date":47,"featured":48,"seoDescription":49,"series":50,"seriesOrder":22},"h5-debug-console-mock","H5 调试实战（二）：Android WebView 白屏排查，从 Console 远程定位到 Mock 验证","活动 H5 在部分 Android 设备中点击按钮后白屏，请求全部 200 却没有页面反馈。通过 DevPeek Console 获取线上 WebView 运行日志，远程 eval 确认 polyfill 覆盖问题，再使用 Mock 验证异常状态下的降级页面。","2026-07-13",true,"H5 调试实战第二篇：排查 Android WebView 白屏问题。通过 Console 远程调试定位 JavaScript polyfill 兼容问题，并结合 Mock 验证接口异常场景下的页面降级逻辑。","h5-debug",{"slug":52,"title":53,"summary":54,"date":55,"featured":48,"seoDescription":56,"series":50,"seriesOrder":29},"wechat-h5-storage-debug","H5 调试实战（一）：微信 H5 localStorage 调试，在电脑上修改真机缓存","微信 H5 换测试号后头像仍显示旧用户，抓包确认接口正常，却定位到 localStorage 遗留旧数据。本文记录一次真实联调过程，以及如何在电脑上查看、修改微信 WebView 的 localStorage、sessionStorage 和 IndexedDB。","2026-07-11","微信 H5 调试实战：通过真实案例定位 localStorage、sessionStorage、IndexedDB 导致的数据缓存问题，对比 vConsole、Remote Debug 等方案，介绍真机 WebView 调试思路。",{"slug":58,"title":59,"summary":60,"date":61,"featured":48,"seoDescription":62,"series":63,"seriesOrder":22},"why-we-built-devpeek-h5-debug","我们为什么做 DevPeek（二）：App 里那页 H5，在电脑上也能对着查","登录接口用参数转换啃下来了，活动页 H5 却在 App WebView 里才崩。真机 remote debug 折腾一圈，DOM 和抓包还是两拨窗口——于是把镜像和自研调试面板收进 DevPeek。","2026-07-10","DevPeek 起源系列第二篇：App 内嵌 H5 只在真机出问题、remote debug 与抓包割裂的联调痛点，以及调试 Tab 如何把页面镜像到电脑并用自研面板查 DOM、Console 与 Network。","origin",{"slug":65,"title":66,"summary":67,"date":68,"featured":48,"seoDescription":69,"series":63,"seriesOrder":29},"why-we-built-devpeek","我们为什么做 DevPeek（一）：HTTPS 解密了，Body 还是天书","版本日前那晚，TLS 早就解开了，改请求里一个字段却还要翻脚本加解密。于是萌生做一个把业务加解密收进代理的工具——DevPeek 从这儿开始。","2026-07-09","DevPeek 起源系列第一篇：联调时请求体加解密的手工折腾，以及为什么先做一款把业务加解密收进代理的工具。",1786681089445]