大家好,我是何三,独立开发者

一张社交媒体分享图,后台要启动一个 300MB 的 Chrome 浏览器。这听起来是不是有点离谱?

但这就是过去几年里,所有用 next/og 或者 Puppeteer 生成 OG 图片的人每天都在干的事——每次用户分享一篇文章,你的服务器就得默默拉起一个完整的浏览器实例,渲染完了再关掉。300MB 内存就为了跑一张 1200×630 的图。

Takumi 干了件很绝的事:把这个过程缩成了一个函数调用。

项目地址:https://github.com/kane50613/takumi

它到底做了什么?

说人话就是——Takumi 在 Rust 里实现了一个完整的渲染管线,从 CSS 布局到文字排版再到像素输出,全部塞进了一个二进制文件。

以前你要生成一张 OG 图:

  1. 启动 Chrome/Puppeteer(300MB RAM)
  2. 加载页面(再吃几十 MB)
  3. 截屏输出
  4. 关掉浏览器

现在你只需要:

import { render } from "takumi-js";

const image = await render(
  < div tw="w-full h-full flex items-center justify-center bg-gradient-to-b from-blue-100 to-red-50">
    < h1 tw="text-6xl font-bold">Hello from Takumi< /h1>
  < /div>,
  { width: 1200, height: 630 },
);

一个 render() 搞定。没有浏览器,没有 300MB 开销,没有冷启动延迟。

说实话,我第一次看到这个的时候真的愣了一下——没懂作者为什么非要用 Rust 从头写一套渲染引擎。后来仔细一想,如果不是 Rust,还真做不到这个效果。

不只是 next/og 的替代品

Takumi 可以当作 next/og 的即插即用替代品——ImageResponse API 完全兼容。但它的能力远不止于此。

这个东西怎么说呢……就是那种……越用越觉得离谱的工具。

我来列几个让我直接惊到的能力:

支持 CSS Grid。 next/og(底层是 Satori)只支持 Flexbox,想排个网格布局你得自己算。Takumi 直接把 Grid 支持做好了,grid-template-columnsgrid-template-rows,随便用。

支持动画输出。 你没看错,它能生成动图——WebP、APNG、GIF,甚至可以直接输出视频帧序列给 ffmpeg 合成视频。CSS @keyframes 动画、animate-spin 这些 Tailwind 动画类,全部支持。

支持 backdrop-filter 和 blend modes。 毛玻璃效果?直接写 backdrop-filter: blur() 就行。

而且它不止能在 Node.js 上用。Cloudflare Workers 可以加载 WASM 构建,浏览器端也行,Rust 项目直接 crate 引用——四个部署目标,一个引擎

// Cloudflare Workers 同步支持
import { render } from "takumi-js";

export default {
  async fetch(req) {
    const image = await render(
      < div tw="w-full h-full flex items-center justify-center bg-black text-white">
        < h1>Hello Workers< /h1>
      < /div>,
      { width: 1200, height: 630 },
    );
    return new Response(image, {
      headers: { "content-type": "image/png" },
    });
  },
};

🏃‍♂️ 跑题联想:Vercel 的 Satori 也做了类似的事

说到这个,我突然想起来 Vercel 的 Satori 也是干这个的——把 JSX 转成 SVG,不需要浏览器。但 Satori 有几个硬伤:只输出 SVG(你拿到的是一堆 <svg> 标签,还得再转一次才能变成 PNG),只支持 Flexbox,不支持 CSS 动画,而且只能在 Node/Edge Runtime 上跑。

Takumi 相当于把 Satori 没做完的事全做完了——而且是用 Rust 在底层重写了一遍

用 Rust 写出这玩意儿,真的服。

老实说,这块的实现细节我没完全搞懂——它底层用了 taffy 做布局、parley 和 skrifa 做文字排版、resvg 处理 SVG,最后用自己写的管线做输出。但原理大概是这样,细节可能有出入——有懂的大佬欢迎指正。

谁在用?

看看这个列表就知道这玩意儿不是玩具:

  • Dcard(台湾最大的社区平台)用来生成文章分享图
  • TanStack 用它在文档里生成 OG 图
  • Fumadocs 集成了 Takumi 作为默认渲染器
  • Nuxt OG Image 把 Takumi 作为内置渲染器之一
  • Luma 用它在活动分享页面上生成图片

而且它是 Vercel OSS Program 的成员项目——也就是说 Vercel 官方也在支持它。

上手体验

装一下试试,一行命令:

bun i takumi-js

然后直接写 JSX:

import { render } from "takumi-js";
import { writeFile } from "node:fs/promises";

const image = await render(
  < div tw="w-full h-full flex items-center justify-center bg-gradient-to-b from-blue-100 to-red-50">
    < h1 tw="text-6xl font-bold">Hello from Takumi< /h1>
  < /div>,
  { width: 1200, height: 630 },
);

await writeFile("./output.png", image);

跑完之后你就会看到一张漂亮的渐变图。这就是 OG 图生成的全部代码了——没有 Docker,没有 Puppeteer,没有 Chrome。

如果你用的是 Next.js,替换就更简单了:

// 之前
// import { ImageResponse } from "next/og";

// 之后
import { ImageResponse } from "takumi-js/response";

export function GET() {
  return new ImageResponse(
    < div tw="...">
      < h1>Hello< /h1>
    < /div>,
    { width: 1200, height: 630 },
  );
}

改一行导入,剩下全不变。

同类项目

如果你对这类"不需要浏览器就能生成图片"的工具感兴趣,还有几个值得看:

  • Satori(Vercel): JSX→SVG,Takumi 的前辈,功能较基础
  • @resvg/resvg(linebender): Rust 写的 SVG 渲染引擎,Takumi 的 SVG 输出背后就用了它
  • Sharp:图片处理是老牌工具,但它不处理 HTML/CSS 渲染

觉得 Rust 生态有意思?我之前还写过一篇关于 Rust 工具链的文章,关注后回复「rust」可以看看。

总结

Takumi 做的事情很纯粹——把 OG 图生成从"开一个浏览器"降到了"调一个函数"。

300MB 的浏览器开销省了,冷启动延迟没了,还能部署到 Cloudflare Workers 上零成本运行。对于任何需要在服务端生成社交分享图的项目来说,这个工具都是降维打击。

装不装都行,看你自己。但你要是还在用 Puppeteer 生成 OG 图……嗯,你懂的。

本文使用 MGO 编辑并发布

关注"何三笔记",回复"mgo" 免费下载使用