tsrs: 在 ENX 项目里试用 Rust 版 TypeScript 类型检查器

起因 先是在微信公众号上看到一篇介绍 tsrs 的文章,又读了 Cloudflare 的公告 Porting TypeScript to Rust。tsrs 在 Oxc 项目下孵化,Oxc 属于尤雨溪的 VoidZero。我一直关注尤雨溪的动向,早年也用过 Vue,对他团队出的东西比较信任,所以想在自己的项目 ENX 上试一下。 ENX 有两个 TypeScript 前端:enx-ui(Next.js)和 enx-chrome(Chrome 扩展,Vite 构建)。两边现在都用 TypeScript 6.0.3。 tsrs 是什么 把 TypeScript 7 的 Go 版编译器(tsgo)逐个函数移植到 Rust,命令行用法和 tsc 一样,许可证是 Apache-2.0。 由 Owner.com 的 Max Schwenk 发起,Cloudflare 和 VoidZero 参与,和 TypeScript 团队有合作。它不是 fork,语言方向仍由 TypeScript 团队决定。 对齐的是 TypeScript 7.1 开发版(microsoft/TypeScript@b85298b6a81f)。官方一致性测试的 13,462 条错误基线通过了 13,458 条,作者说剩下 4 条是测试工具本身的问题。 Cloudflare 的数据:同样数量的检查线程下,tsrs 比 TypeScript 7.0 快最多 8 倍,内存少约 70%。 仓库 2026-10-01 才建,到我试的时候已经发到 0.18.0。仓库不接受 PR。不支持 --init 和 --showConfig,没有 Intel Mac 二进制,Windows 包还没发布。 试用过程 为了不动项目依赖,我把 tsrs 装在一个临时目录里,再用它的二进制去检查两个前端: ...

Created 21216-10-21 · Updated 21216-10-21 · 2 min · 263 words · -

Turbopack

Turbopack 是 Vercel 开发的 JavaScript/TypeScript 打包工具(bundler),用 Rust 编写,定位是 Webpack 的继任者。它目前主要通过 Next.js 使用:从 Next.js 16 开始,next dev 和 next build 默认都用 Turbopack。 打包工具做什么 浏览器不能直接运行一个现代前端项目的源码:TypeScript 和 JSX 要编译成 JavaScript,import 了上百个 npm 包的模块图要合并、拆分成若干个文件,CSS、图片要处理,生产环境还要压缩、去掉没用到的代码(tree shaking)。打包工具做的就是这件事:从入口文件出发,沿着 import 建出完整的模块图,再按规则输出浏览器和 Node.js 能直接加载的文件。 Next.js 这类同时有服务端和客户端代码的框架,还要求打包工具同时产出两套结果:服务端渲染用的代码,和发给浏览器的代码。 常见的打包工具: 工具 实现语言 说明 Webpack JS 2012 年起的事实标准,插件和 loader 生态最大 Rollup JS 偏库打包,Vite 的生产构建原先基于它 esbuild Go 速度快,常被其他工具当作底层编译器 Vite JS 开发模式基于浏览器原生 ESM,正在把底层换成 Rust 实现 Turbopack Rust Vercel 出品,与 Next.js 绑定 背景 Webpack 统治前端工程化十余年,但它用 JavaScript 实现,项目一大,冷启动和热更新都慢。Vercel 在 2022 年随 Next.js 13 发布了 Turbopack 的 alpha 版。Webpack 的原作者 Tobias Koppers 是 Turbopack 的核心作者之一。 ...

Created 10106-06-10 · Updated 12126-10-12 · 2 min · 378 words · -

Rust Basic

Rust Basic Rust 是一种 AOT 编译(ahead-of-time compiled)的静态类型语言,编译型 / 解释型对照见 Compiled vs Interpreted。 Rustup Rust 的工具链管理器 Rustup 是一个命令行应用,能够下载并在不同版本的 Rust 工具链中进行切换 —— 如编译器 rustc 和标准库,该应用所支持的平台数量不少。事实上,rustc 本身就支持大约 56 个平台,而 rustup 实际上能够为其中14个平台管理编译器,为30个平台管理标准库。 Rust 1.8 中引入的 Rustup,是一个针对 Rust 语言的工具链管理器(toolchain manager),其目标是让交叉编译 Rust 代码更加简单。Mozilla 工程师 Brian Anderson 近期与我们分享了关于此的更多细节。 此外,rustup 能够追踪工具链的具体版本,包括 Rust 的 nightly 版本、beta 版本和发行版本。举个例子,你可以用 rustup 检查程序在下一个 Rust 发行版下的行为。但是之前,你需要安装当前平台下的 Rust beta 版本的工具链,然后利用该工具链运行单元测试。使用 rustup 之后,可以通过执行类似下面的代码完成: $ rustup install beta $ rustup run beta cargo test 再举一个例子,Anderson 介绍了如何使用 rustup 为使用 musl 标准库(而非大家常用的glibc标准库)的 Linux 版本创建静态二进制文件: ...

Created 1016-01-01 · Updated 9096-10-09 · 2 min · 326 words · -

2026 W30-W31

这两周的周记合成一篇。 enx:先把功能做完,上线再说 enx 是我自己的项目,一个查词加翻译的 Chrome 扩展。这两周它是主线。 前一周主要在部署链路上:调查词性能(SQLite 相关的调整、给 words 表加索引的 migration),构建时把 version 注入镜像,Go API、Java API 和 UI 三条镜像链路陆续跑通,部署到 homelab。 后一周是功能推进: 合入本地 ECDICT 词典,查词路径不再依赖外部接口 单词弹窗迁到 React + Shadow DOM,样式不会再被宿主页面污染 加了句子翻译的 Side Panel,翻译后端做成多 provider(MiniMax、Bedrock、Kimi),用 factory 加 handler 分派 修扩展的 session 超时问题,Cognito 那边改成手写刷新逻辑 周六在岛上想清楚一件事:微信登录先不做了。现在已经有 Google 登录,把 Stripe 接上就可以上线部署。把基本功能做完先上线,不需要等到完美。 一个朋友的文档校验工具 之前写过的、给一位朋友做的文档校验工具,这两周继续往前走。 前一周主要是仓库骨架落地:架构 ADR、几个模块的 Spec、测试,周末开始写 Web UI 的 SDD 和 lint 配置。后一周把它部署进了测试环境。 另外这个项目按正常的需求分析、报价流程走一遍。因为如果以后真的在线接单,报价是绕不开的问题,正好拿它测试一下。 starlabrys 官网 公司官网这两周加了历史项目展示页,还有一个 Site Advisor 的雏形,包括意图识别、知识库、tools 和对话几个部分。ew8 帮我改的那部分周五合并进来了。 w_dashboard:一个玩具级的仓库看板 周末起了个新项目 w_dashboard,Linux 端用 Rust 加 Slint,macOS 端用 Swift 加 SwiftUI,两端各写了一版初版。 ...

Created 2026-08-02 · Updated 2026-08-02 · 1 min · 130 words · -

Compiled vs Interpreted: 编译型、解释型与脚本语言

背景 教材里常把编程语言分成 编译型(compiled) 和 解释型(interpreted)。二者是一组相对概念,但现代语言大多落在光谱中间,不宜一刀切。 脚本语言(scripting language) 在日常说法里,往往就是解释型一侧的别名,或更窄一点:强调「缩短 edit-compile-link-run、以源码直接跑、做自动化 / 嵌入」的那一类解释型语言。下文先讲编译 / 解释,再单独说脚本。 两种执行路径 类型 典型流程 运行时依赖 编译型 源码 → 编译器 → 机器码 / 本地二进制 → 直接由 OS 加载执行 一般不需要语言自带的解释器;可内嵌 runtime(如 GC) 解释型 源码(或中间表示)由 解释器 边读边执行 必须安装对应解释器 / 运行时 对照: 编译型(AOT): 源码 ──compile──► 本地二进制 ──► 运行 解释型: 源码 ──► 解释器逐句执行 字节码 + VM: 源码 ──compile──► 字节码 ──► 解释 / JIT ──► 机器码 「预编译 / ahead-of-time(AOT)」说的是:运行前就编成可执行形态;日常口语里常与「编译型」混用。注意 C 里的「预编译」有时指 #include / #define 的预处理,那是编译流水线的一步,不是语言分类。 ...

Created 1016-08-01 · Updated 1016-08-01 · 2 min · 395 words · -

Swiss Table 哈希表

Swiss Table 是什么 Swiss Table 是 Google 在 2017 年前后公开的一种高性能哈希表设计(最早用在 Abseil 库的 absl::flat_hash_map 里),本质上是开放地址法的一个工程变体:在经典的线性探测 / 二次探测之上,加入了按"组"批量比较的机制,充分利用 CPU 的 SIMD 指令与缓存局部性。基本的开链法、开放地址法概念见 开链法与开放地址法。 它已经被多个主流项目采纳:Rust 的 hashbrown(std::collections::HashMap 自 1.36 起的底层实现)就是 Google SwissTable 的 Rust 移植版;Go 1.24 内置的 map 也从桶+溢出桶的实现换成了基于 Swiss Table 思路的新实现(细节见 开链法与开放地址法#在-go-语言中的应用)。 核心设计 控制字节(control byte) Swiss Table 给每个槽位(slot)配一个额外的 1 字节"控制字节",不存实际数据,只存槽位的状态和一段哈希指纹: 槽位状态:EMPTY(从未用过)、DELETED(曾经用过、已删除,即墓碑标记)、FULL(当前有效数据)。 如果槽位是 FULL,控制字节里还会存一段哈希指纹,Abseil 里称为 h2,取的是 key 完整哈希值的低 7 位。 h1 和 h2:哈希值一分为二 Swiss Table 把 key 的哈希值拆成两部分: h1:哈希值的剩余高位,用来计算这个 key 应该落在哪一个"组"(group),即决定探测起点,作用类似前文开放地址法里的 root = hash(key) % m。 h2:哈希值的低 7 位,存进控制字节,作为一个廉价的"预筛选"指纹。 分组批量比较 控制字节在内存中是连续排列的,按组打包(Abseil/hashbrown 里一组 16 个,Go 1.24 里一组 8 个,打包进一个 64 位控制字)。查找时: ...

Created 13136-07-13 · Updated 13136-07-13 · 2 min · 399 words · -