写过前端的人都踩过这个坑——CSS 值想在 Worker 里做运算,只能先序列化成字符串。今天 Chrome 153 把这件事彻底原生化了

写过一个用 Worklet 做动画的前端工程,遇到过这个问题:主线程和 Worker 之间传 CSS 值,只能靠字符串。CSS.px(100) 这种东西,在 Worker 里根本不存在,你只能把它转成 100px 字符串发过去,Worker 里再 parse 回来,类型全丢了,一不小心还容易出 bug。

这就是 Chrome 153 要修的坑。

这个问题到底是什么

CSS Typed OM(即 CSS Houdini 的类型化对象模型)让开发者可以用有类型的 JavaScript 对象操作 CSS 值——比如 CSS.px(100) 返回一个 CSSUnitValue 对象,里面有 .value.unit 属性,比 100px 字符串好使多了。

但是,Blink 引擎(Chrome/Edge 用的渲染引擎)之前只把这些类的构造函数暴露给 Window 上下文,Worker 和 Worklet 里面根本找不到 CSSUnitValueCSSNumericValue 这些类。你在 Worklet 里写 new CSSUnitValue(100, px)?浏览器直接报错:CSSUnitValue is not defined

所以之前在 Worker 里处理 CSS 值,只能靠字符串——先把值序列化成字符串传进去,Worker 里用 parseInt / parseFloat 硬拆,拆完再拼回字符串。类型安全?没有。单位换算?自己写。跨线程传值?字符串是最可靠的格式。

Chrome 153 把这件事修了

Chrome 153(2026 年 9 月 2 日 Beta,9 月 9 日稳定版)把 CSS Typed OM 的类层次完整暴露给了 Worker 环境:[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)]。

这下 Worker 里能用的类包括:

  • CSSStyleValue — 基类,所有类型化 CSS 值的父类
  • CSSUnitValueCSS.px(100) / CSS.em(2) / CSS.percent(50),带单位的数值
  • CSSNumericValue — 所有数值类型的父类,数学运算的入口
  • CSSKeywordValueCSS.keyword(auto),关键字值
  • CSSUnparsedValue — 还没 parse 的原始 CSS 字符串
  • CSSTransformValue — skew/scale/rotate 等变换矩阵
  • CSSPositionValueCSS.position(CSS.px(10), CSS.percent(50)),坐标值
  • CSSImageValue — 图片类型值

在 Worker 里能干什么

一个最直接的场景:Paint Worklet 写自定义背景。

// ❌ 以前:只能收到字符串
// main thread → worker: 100px
// worker 里: parseInt(100px) → 100

// ✅ 现在:直接收到 CSSUnitValue
// main thread → worker: CSS.px(100)
// worker 里: value.unit → px, value.value → 100
registerPaint(my-panel, class {
  static get inputProperties() {
    return [--my-width, --my-unit];
  }
  paint(ctx, geom, styleMap) {
    const w = styleMap.get(--my-width);   // CSSUnitValue
    const unit = styleMap.get(--my-unit); // CSSKeywordValue
    // 可以直接拿数值做运算,unit 不丢失
    const px = w.to(px);
    ctx.fillRect(0, 0, px.value, 50);
  }
});

另一个场景:Layout Worklet 读取尺寸。

// 读取元素尺寸,单位自动跟随
const width = styleMap.get(width); // CSSUnitValue
const height = styleMap.get(height);
// 两者单位可能不同:px / em / rem
// 可以直接换算:width.to(rem) → 换算成 rem

还有一种用法:在 Worker 里做 CSS 值运算,再传回主线程。以前你要把运算结果转成字符串,主线程再 parse——现在可以直接传 CSSUnitValue 对象。

实际意义:主线程终于能彻底减负了

CSS Typed OM 进 Worker 真正的价值,是让 CSS 相关的计算彻底脱离开主线程。

之前把 CSS 处理逻辑放进 Worker 是有代价的——你要自己维护一套序列化/反序列化逻辑,单位换算自己来,类型安全自己保。Typed OM 进 Worker 之后,Worker 里可以直接用这些类型化的 API,运算完了直接传回去,主线程不用再做一次 parse。

对 Paint Worklet 和 Layout Worklet 来说尤其重要——这两个 Worklet 本身就是用来在主线程之外干活的,之前缺了 Typed OM,相当于少了一整套工具。

兼容性:不用等了

Firefox 和 Safari 早就完整支持了,Chrome 153 这次是补齐最后一块短板,全球覆盖率约 90%。

用法不需要任何 polyfill,@supports 渐进增强即可:

// Worker 里检测
if (typeof CSS !== undefined && CSSUnitValue) {
  // Typed OM 可用
}

下一步

如果你现在在用 CSS Houdini Paint Worklet 或 Layout Worklet,检查一下代码里有没有把 CSS 值转字符串再 parse 的地方——那些现在可以直接删掉,让 Worker 里的 Typed OM 来处理。

如果你还没用过 Worklet,Typed OM 进 Worker 是个很好的切入点:之前不敢用的理由少了一个,是时候试试把动画逻辑搬到 Worklet 里面,彻底让主线程省心了。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 10 阅读