#vue #compiler #style #css #transformer

fervid_css

Vue <style> 块的转换器

3 个版本 (破坏性更新)

0.2.0 2024年7月7日
0.1.0 2023年12月11日
0.0.1 2023年5月10日

开发工具 中排名第 847

Download history 172/week @ 2024-07-06 45/week @ 2024-07-13 68/week @ 2024-07-20 20/week @ 2024-07-27

每月下载量 305
5 个包中使用(通过 fervid_transform

Apache-2.0

73KB
1.5K SLoC

fervid

用Rust编写的全功能Vue编译器。目前处于alpha阶段,最接近的目标是达到与当前 Vue SFC编译器 的功能一致性。

入门

如何在Vue CLI和Vite中使用fervid的说明即将推出!

MVP进展 84%

项目的最小目标包括(见 路线图

  • Vue 3代码生成;
  • unplugin 集成;
  • Farm 原生插件;
  • Dev/prod模式支持;
  • 支持 <script setup>
  • 带配置的示例Vue项目;
  • 性能比较。

这是正确的吗?

该项目使用 Vue SFC playground 作为其参考,以比较输出。截至2023年11月,fervid能够生成与官方编译器几乎相同的DEV和PROD代码,但在某些方面存在一些差异。

  • 上下文变量。这包括如 {{ foo + bar.buzz }}<div v-if="isShown"> 这样的用法。在 fervid 中对它们的支持几乎已经完成。
  • [WIP] 修补标志。这些用于帮助 Vue 运行时在比较 VNodes 时。如果一个 VNode 只有一个动态属性,而其他属性和文本都是静态的,则需要将此信息传达给 Vue 以实现快速更新。对这些的支持正在进行中。

要检查 fervid 的正确性,可以将 沙盒输出官方编译器 的输出进行比较。

请注意,输出的“正确性”将取决于 Vue 的版本,因为 Vue 团队可能会更改编译器的输出和行为。这对 fervid 来说是一个挑战。

它快吗?

是的,它非常快。实际上,下面是一个针对 测试组件 的基准测试运行。

  @vue/compiler-sfc:
    954 ops/s, ±1.15%     | slowest, 98.42% slower

  @fervid/napi sync:
    6 464 ops/s, ±0.08%   | 89.29% slower

  @fervid/napi async (4 threads):
    11 624 ops/s, ±2.12%  | 80.73% slower

  @fervid/napi async CPUS (23 threads):
    60 329 ops/s, ±0.67%  | fastest

注意:结果是在 AMD Ryzen 9 7900X 上运行的 Fedora 38,内核版本为 6.5.9。

使用 benny 在 Node.js 中进行了基准测试,略微修改以考虑 libuv 线程。请参阅 基准测试的源代码

更好的基准测试是一个待办事项,其优先级低于功能完整性和实际场景中的可用性,因此 欢迎提交拉取请求

软件包

fervid wip

主要软件包。它导出 compile 方法,该方法将所有阶段连接在一起,从接受源字符串到输出编译后的代码和资产。对于更细粒度的编译,可以直接使用其他软件包。

fervid_core alpha

跨软件包共享的核心结构和功能。

fervid_parser alpha

基于 swc_html_parser 的 Vue SFC 解析器。

fervid_transform alpha

该软件包负责 AST 转换。处理 <script><script setup> 分析和转换,以及 TypeScript。基于 SWC,并提供快速且正确的转换,而无需使用正则表达式。

fervid_css alpha

支持在 <style> 块中工作,并启用 scoped 样式、CSS Modules 和 Vue 特定转换。这个库的核心是 swc_css_parser

fervid_napi alpha

NAPI-rs 绑定,用于在 Node.js 中使用。

fervid_deno future

Deno 绑定,用于在 Deno 中使用。

fervid_pluginfervid_plugin_api future

这些 crate 允许使用动态加载的库(.so.dll.dylib)在 Rust 中编写 fervid 插件。这些插件允许任何人对 Vue SFC 的解析、优化和代码生成进行自定义。

路线图

解析器

  • 模板解析
  • W3C 规范兼容性

转换器

  • 模板作用域构建
  • 错误报告
  • JS/TS 导入分析(由 swc_ecma_parser 提供)
  • setup/data/props 分析
  • 处理 <style scoped>
  • 支持 <script setup>
    • 绑定收集;
    • 返回语句:内联与渲染函数;
    • defineProps
    • defineEmits
    • defineExpose
    • defineOptions
    • defineSlots
    • defineModel
    • 测试

代码生成器

  • 基本的 Vue3 代码生成

    • 元素
      • createElementVNode
      • 属性
        • 静态 + 动态
        • style 合并
        • class 合并
      • 子元素
    • 组件
      • createVNode
      • 插槽
    • 上下文感知(_ctx$data$setup
    • 指令
      • v-on
      • v-bind
      • v-if / v-else-if / v-else
      • v-for
      • v-show
      • v-slot
      • v-model
      • v-cloak
      • v-html
      • v-memo
      • v-once
      • v-pre
      • v-text
      • 自定义指令
    • 内置组件
      • keep-alive
      • component
      • transition
      • transition-group
      • teleport
      • slot
      • suspense
    • 补丁标志
    • 提升
  • DEV/PROD 模式

  • 热模块替换 (HMR)

  • Vue 2.7 支持

  • SSR 与内联关键 CSS 支持

  • Vue 导入的急切预编译(避免不必要的 bundler->compiler 调用)

集成


lib.rs:

Vue <style> 块的样式转换器

示例

use swc_core::common::{Span, BytePos};

let input = r#"
.example {
  background: #ff0;
}
"#;

// Note: `Span` usually comes from the input, e.g. from `<style>` block
let span = Span::new(
    BytePos(1),
    BytePos(1 + input.len() as u32),
    Default::default(),
);
let mut errors = Vec::new();

let result = fervid_css::transform_css(input, span, Some("data-v-abcd1234"), &mut errors, Default::default());

if let Some(transformed_css) = result {
    assert_eq!(".example[data-v-abcd1234]{background:#ff0}", transformed_css);
}

依赖项

~13MB
~294K SLoC