3 个版本 (破坏性更新)
0.2.0 | 2024年7月7日 |
---|---|
0.1.0 | 2023年12月11日 |
0.0.1 | 2023年5月10日 |
在 开发工具 中排名第 847
每月下载量 305 次
在 5 个包中使用(通过 fervid_transform)
73KB
1.5K SLoC

fervid
用Rust编写的全功能Vue编译器。目前处于alpha阶段,最接近的目标是达到与当前 Vue SFC编译器 的功能一致性。
入门
如何在Vue CLI和Vite中使用fervid
的说明即将推出!
MVP进展 
项目的最小目标包括(见 路线图)
这是正确的吗?
该项目使用 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

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

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

基于 swc_html_parser 的 Vue SFC 解析器。
fervid_transform

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

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

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

Deno 绑定,用于在 Deno 中使用。
fervid_plugin
和 fervid_plugin_api

这些 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 调用)
集成
- WASM 二进制文件(未发布)
- NAPI 二进制文件 @fervid/napi
- unplugin(进行中)
- Farm 原生插件
- Turbopack 插件(当插件系统定义后)
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