2024年,一个法国开发团队为了摆脱Node.js依赖,用OCaml写了一套完整的CSS工具链。最终产物Cascade有3万行代码,能解析、生成、优化、对比现代CSS——包括Tailwind v4才支持的@layer和容器查询。这相当于用一门40岁的函数式语言,造了一把前端工程化的瑞士军刀。
事情的起因很具体:Thomas Gazagnaire想给自己的网站换皮肤,却发现整个构建流程被Node.js绑架了。
他是MirageOS核心开发者,网站用OCaml写的,样式用Tailwind CSS。每次改样式都要启动Node生态,这让他不舒服。「我想让Markdown到样式化HTML再到CSS,全是单个dune构建,零Node依赖。」他在博客中写道。
移植Tailwind的CSS生成逻辑到OCaml,需要验证输出是否正确。但现成的CSS对比工具要么 abandoned(被遗弃),要么只支持CSS 2/3,对@layer、容器查询、嵌套规则和现代色彩空间全部抓瞎。
于是他开始写一个diff工具。这需要解析器。解析器需要类型化的AST。AST需要优化器。三个月后,Cascade诞生了。
从字符串到AST:一次编译期保险
Cascade的核心设计是把CSS变成强类型的OCaml数据。解析器用手写递归下降实现,覆盖CSS Syntax Level 3到Level 5。输入一段带重复规则的CSS:
`.btn`出现了两次,这在生成式CSS里很常见——不同模块各自输出自己的样式,最后拼在一起。
Cascade的解析器保留两个规则,返回类型化的AST。如果你用OCaml的eDSL直接构造规则,拼写错误如`dsiplay`会在编译期报错,把颜色传给`padding`也是类型错误。这是动态CSS预处理器做不到的事。
生成阶段,AST可以渲染为格式化或压缩的CSS。打印器会自动优化:white变成#fff。优化阶段更激进:合并重复的`.btn`规则,按层叠顺序保留最后的`background-color`,同时尊重`!important`和故意留下的内容回退模式。
cssdiff:结构级对比,不是文本diff
Cascade附带的cssdiff工具解决了一个真实痛点:验证移植后的CSS生成器是否与原版行为一致。
文本diff对CSS没用。两个文件可能写法不同但语义相同——属性顺序调换、简写展开、十六进制大小写差异。cssdiff做结构级比较,理解选择器优先级、层叠规则和继承。
因为它是纯OCaml,可以通过js_of_ocaml编译到浏览器运行。Gazagnaire在博客里放了在线演示,可以上传两份CSS看差异,或选预设样例。
为什么选OCaml?不是炫技,是生态位
OCaml社区有个特点:同一批人反复重写自己的基础设施。Gazagnaire的博客就经历过ocaml-cow、Canopy、自定义MirageOS unikernel多次迭代。这次轮到CSS工具链。
这种「重复造轮子」在工业界是浪费,在函数式语言社区是特征。每轮重写都利用类型系统的新能力,把运行时错误变成编译期错误。Cascade的eDSL让CSS构造具备OCaml的类型检查,相当于给样式层加了静态分析。
对目标用户——25-40岁的科技从业者——这个案例的价值在于:它展示了如何把「逃离Node.js依赖」这个具体痛点,拆解成可验证的技术步骤。不是喊口号,是写3万行代码,覆盖CSS标准的边缘情况,再配一个浏览器可运行的diff工具。
项目已开源。Gazagnaire在博客结尾说,Cascade现在对他够用了,但欢迎贡献。如果你也在维护一个想摆脱Node.js的OCaml项目,或者只是好奇强类型CSS长什么样,可以去试那个在线demo。
最后一个细节:演示页面的示例选择器里,有一项叫「Tailwind v4 output」。这说明他们已经在用这套工具追踪最前沿的CSS生成器行为——不是追过去,是追正在发生的事。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.