为什么一切都在浏览器中运行
我们创建这个网站,是因为2018年我们信任的几乎每一个JSON格式化工具都会把我们的负载发送到服务器。我们只是想格式化一个内部API响应。粘贴之后页面卡了一秒,我们突然意识到:现在有别人拿到了半条客户记录的副本。虽然没有酿成大祸,但那是会让人记一辈子的瞬间。
我曾经把一个JWT粘贴到某个『免费』解码器里,泄露了一个生产环境的AWS访问密钥——那个解码器还『贴心地』把请求头也记录了下来。同一个小时内,那个令牌就被挂进了Lambda调用。我们在十五分钟内轮换了密钥并重建了部署流水线。那次经历就是这个网站存在的全部理由,也是这里每个工具都以静态SvelteKit页面运行、在你的浏览器而不是我们的基础设施上完成工作的原因。
我们的网络日志很无聊:页面的一次GET,字体和脚本包的几个请求,仅此而已。不存在任何可以悄悄接收你输入的POST端点。想验证的话,打开DevTools,一边编码200 KB的文本一边盯着Network标签页,你会看到对外请求正好是零。
我们实际测量过的性能
在运行Chrome 130的2024款M2 MacBook Pro上,我们的JSON格式化工具端到端处理50 MB负载约需1.18秒,渲染树再过240毫秒即可显示。我们用GitHub events归档做测试,里面那种层层嵌套的数组曾让我们对比测试的三个格式化工具直接败下阵来。
同一台机器上,对100 MB二进制数据做Base64编码需要380毫秒。解码同一负载需要410毫秒——更慢是因为我们会对输入长度做一次健全性检查。在运行Chrome 130的Pixel 8上,这两个数字分别是1.4秒和1.6秒。我们列出的是最坏情况而不是最好情况,因为最好情况会说谎。
哈希计算直接使用WebCrypto API。100 MB的SHA-256在M2上是220毫秒,在Pixel上是480毫秒。MD5(为兼容性保留的遗留算法)是我们用纯JS写的,比SHA-256慢大约4倍——这个差距就是没有浏览器原生实现的代价。如果你真的要在安全场景用MD5,那你不应该用。我们做这个工具,是因为老系统的校验和仍然会要求它。
这个网站是怎么构建的
整个网站是构建在Vite之上的SvelteKit。2024年我们选择Svelte而不是React,因为工具类网站的包体积必须小——JSON格式化工具加载时只带14 KB而不是80 KB的框架代码。代价是Svelte的生态更小,在挑选语法高亮库时我们切实感受到了这一点,最后为diff工具自己写了一个。
我们部署在Cloudflare Pages上。构建通常在三十秒内完成,工具页面的冷启动时间主要花在SvelteKit的水合(hydration)步骤上,而不是网络。我们采用SSR + CSR混合模式:页面带着预渲染好的标记发出,让搜索爬虫和AI摘要器看到真实内容,等你到达时JavaScript再水合出真正的工具。
整个仓库不到三千行TypeScript。任何读过代码的人都应该能通过复制一个现有工具、在大约九十分钟内加出一个新工具——这是刻意的设计约束,因为我们希望在工作中一遇到用例就能上线一个新工具。这里大约一半的工具,起点都是Slack里一句『要是有个私密版的这玩意就好了』。
我们不是什么
我们不是SaaS。没有账号、没有用量套餐、没有API令牌。如果你想用脚本调用这些工具,它们所封装的npm包通常搜一下就能找到——我们在每个工具的文档页里都放了链接。
我们也不做PII存储。虽然一切都在本地运行,但默认情况下我们连localStorage都不写。少数工具(计数器、颜色选择器)选择性地记住上一次的值,但页面上会写明,而且你可以随时清除。
我们不追逐世上存在的每一种工具。只有当认识的开发者提出需求,或者我们自己在同一周里需要了两次,才会新增一个工具。写这段话时共有23个工具。以后会更多,但会慢慢来。
看起来简单、实则费时的小决定
深色主题默认就是深色,而不是跟随系统偏好。我们测试了一个月的系统偏好模式,看到廉价笔记本用户的跳出率上升——那些Windows默认浅色模式、屏幕却泛白的机器。默认深色、配一个清晰的切换开关,最终表现更好——所谓更好,是指人们在页面上停留的时间足够用完工具。
我们给输入框选了等宽字体,其余部分用比例字体。听起来理所当然,但早期版本到处用同一种字体,用户不断反馈长URL和JWT字符串看起来是坏的。修复只是一次十五分钟的CSS改动。找到正确的诊断,却花了好几周盯着热力图录像。
每个工具都有一个『示例』按钮,加载一段有代表性的输入。我们是在看了太多这样的会话回放之后加的:用户打开工具,对着空输入框看十秒,然后离开。示例也故意不做到完美干净,因为有一半的时候你其实想调试的就是格式不对的输入。