herringtondarkholme / vue-compiler Goto Github PK
View Code? Open in Web Editor NEWVue's template compiler reimplemented in Rust!
License: MIT License
Vue's template compiler reimplemented in Rust!
License: MIT License
For the example below with TS generics:
<script setup lang="ts">
import { shallowRef } from 'vue'
import { NCard } from 'naive-ui'
const root = shallowRef<InstanceType<typeof NCard>>()
</script>
It compiles:
const _Vue = Vue
const {
createVNode: _createVNode, createElementVNode: _createElementVNode, createTextVNode: _createTextVNode,
} = Vue
const _hoisted_0 = {
setup: "",
lang: "ts",
}
return function render(_ctx, _cache) {
with (_ctx) {
const {
createVNode: _createVNode, createElementVNode: _createElementVNode, createTextVNode: _createTextVNode, resolveComponent: _resolveComponent, withCtx: _withCtx,
} = _Vue
const _component_InstanceType60typeof = _resolveComponent(InstanceType [
_createTextVNode(">()\n")
]),
_: 1 /*Stable*/,
},
]),
])
}
}
which looks wrong.
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
package: /Users/wuls/Desktop/rust/vue-compiler/crates/wasm/Cargo.toml
workspace: /Users/wuls/Desktop/rust/vue-compiler/Cargo.toml
warning: profiles for the non root package will be ignored, specify profiles at the workspace root:
package: /Users/wuls/Desktop/rust/vue-compiler/napi/Cargo.toml
workspace: /Users/wuls/Desktop/rust/vue-compiler/Cargo.toml
error: found a virtual manifest at /Users/wuls/Desktop/rust/vue-compiler/Cargo.toml
instead of a package manifest
I follow this doc,
it will be an error
hi there,
currently I am trying the file parsing part by directly importing the crate vue-compiler-core
.
Is it possible to remove once_cell
feature? or any advice for the replacement of once_cell?
sorry for my dumb asking, but I think it is not a good idea to build with the nightly feature
TLDR: Rslitn is still better than swc.
The code changes are in swc branch and rslint branch.
swc contains a lot of dependencies regardless if they are relevant to core parsing. Such bloated dependencies place huge burden to compiling, slowing rust-analyzer to almost freezing.
swc's docs and examples re scarce. The only working example is https://rustdoc.swc.rs/swc_ecma_parser/.
Looking to the code is also hard. The abstraction and module organization is, well, hazy at least to the uneducated. Peeking the definition is hard, if possible, given the massive usage of macros. Alas, the macro is also the perpetrator of the sluggish compilation. :/
Using swc is not a nice journey, actually. Looking at the example above, it immediately requires several crates other than the parse. common
, ast
, atom
, visit
and blahblah. And the core impl Visitor
has 200+ macro generated methods to implement without one single line of documentation. The usability is poor... And the output is large, merely importing swc pushes the binary size to 33MB.
Rslint at least has more comments and documentation than swc. It's underlying crate, rowan, also has docs. So it might be a better choice. Rslint's dependencies are also more lightweight. Rslint's source code is also simple and clear, compared to swc.
Understanding Green/Red tree does require some learning. But it is fine.
The binary size is 10MB after importing Rslint, one third of swc.
compiler-core/src/transforms/vFor.ts|304 col 15| const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
compiler-core/src/transforms/vFor.ts|307 col 18| const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
compiler-core/src/transforms/vOn.ts|19 col 12| const fnExpRE = /^\s*([\w$_]+|\([^)]*?\))\s*=>|^\s*function(?:\s+[\w$]+)?\s*\(/
compiler-core/src/utils.ts|79 col 17| const whitespaceRE = /\s+[.[]\s*|\s*[.[]\s+/g
shared/src/normalizeProp.ts|30 col 20| const listDelimiterRE = /;(?![^(]*\))/g // ; followed by no single )
compiler-core/src/parse.ts|60 col 13| const decodeRE = /&(gt|lt|amp|apos|quot);/g
compiler-core/src/transforms/vFor.ts|308 col 18| const stripParensRE = /^\(|\)$/g
compiler-core/src/utils.ts|66 col 20| const nonIdentifierRE = /^\d|[^\$\w]/
compiler-core/src/utils.ts|77 col 26| const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/
compiler-core/src/utils.ts|78 col 21| const validIdentCharRE = /[\.\?\w$\xA0-\uFFFF]/
shared/src/normalizeProp.ts|31 col 24| const propertyDelimiterRE = /:(.+)/
shared/src/escapeHtml.ts|1 col 13| const escapeRE = /["'&<>]/
compiler-dom/src/transforms/stringifyStatic.ts|142 col 15| const dataAriaRE = /^(data|aria)-/
compiler-sfc/src/parse.ts|333 col 12| const splitRE = /\r?\n/g
compiler-sfc/src/parse.ts|334 col 12| const emptyRE = /^(?:\/\/)?\s*$/
compiler-sfc/src/parse.ts|335 col 14| const replaceRE = /./g
compiler-sfc/src/rewriteDefault.ts|4 col 20| const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
compiler-sfc/src/rewriteDefault.ts|5 col 25| const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/s
compiler-sfc/src/rewriteDefault.ts|6 col 25| const exportDefaultClassRE =
compiler-sfc/src/stylePluginScoped.ts|5 col 20| const animationNameRE = /^(-\w+-)?animation-name$/
compiler-sfc/src/stylePluginScoped.ts|6 col 16| const animationRE = /^(-\w+-)?animation$/
compiler-sfc/src/cssVars.ts|15 col 20| export const cssVarRE = /\bv-bind\(\s*(?:'([^']+)'|"([^"]+)"|([^'"][^)]*))\s*\)/g
ref-transform/src/refTransform.ts|28 col 21| const transformCheckRE = /[^\w]\$(?:\$|ref|computed|shallowRef)?\s*(\(|\<)/
Why does the output ast structure have no child nodes when I parse the sfc with vue-compiler-core
use vue_compiler_core::{
error::ErrorHandler,
parser::{ParseOption, Parser},
scanner::{ScanOption, Scanner, TextMode, TokenSource},
};
pub use vue_compiler_core::parser::AstRoot;
pub struct NoopErrorHandler;
impl ErrorHandler for NoopErrorHandler {}
fn scan_with_opt(s: &str, opt: ScanOption) -> impl TokenSource {
let scanner = Scanner::new(opt);
let ctx = NoopErrorHandler;
scanner.scan(s, ctx)
}
pub fn base_scan(s: &str) -> impl TokenSource {
scan_with_opt(s, ScanOption::default())
}
pub fn base_parse(s: &str) -> AstRoot {
let tokens = base_scan(s);
let parser = Parser::new(ParseOption {
..ParseOption::default()
});
let eh = NoopErrorHandler;
parser.parse(tokens, eh)
}
will parse code
<script setup>
useHead({
title: 'Nuxt Turbo App',
link: [
{
rel: 'icon', type: 'image/png', href: '/images/nuxt.png',
},
],
})
</script>
<template>
<NuxtLayout>
<NuxtPage></NuxtPage>
</NuxtLayout>
</template>
<style>
html, body , #__nuxt{
height: 100vh;
margin: 0;
padding: 0;
}
html.dark {
background: #222;
color: white;
}
</style>
parse result ast
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
Warning
These dependencies are deprecated:
Datasource | Name | Replacement PR? |
---|---|---|
npm | npm-run-all |
These updates are currently rate-limited. Click on a checkbox below to force their creation now.
@typescript-eslint/eslint-plugin
, @typescript-eslint/parser
)These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
@vue/compiler-core
, @vue/compiler-sfc
, vue
)@typescript-eslint/eslint-plugin
, @typescript-eslint/parser
)benches/Cargo.toml
criterion 0.5
glob 0.3.1
crates/cli/Cargo.toml
anyhow 1.0.79
clap 4.4.18
path-clean 1.0.1
codespan-reporting 0.11.1
serde_yaml 0.9.30
crates/compiler/Cargo.toml
smallvec 1.12.0
bitflags 2.4.2
rustc-hash 1.1.0
serde 1.0
rslint_parser 0.3.1
phf 0.11
lazy_static 1.4.0
insta 1.34.0
crates/dom/Cargo.toml
phf 0.11
crates/sfc/Cargo.toml
smallvec 1.12.0
rustc-hash 1.1.0
ast-grep-core 0.5.3
tree-sitter-typescript 0.20.3
lazy_static 1.4.0
crates/ssr/Cargo.toml
crates/wasm/Cargo.toml
wasm-bindgen 0.2.90
wee_alloc 0.4.5
napi/Cargo.toml
napi 2.14.2
napi-derive 2.14.6
napi-build 2
mimalloc 0.1
.github/workflows/baseline.yml
actions/checkout v4
actions/setup-node v4
actions/cache v3
pnpm/action-setup v2.4.0
benchmark-action/github-action-benchmark v1
.github/workflows/benchmark.yml
actions/checkout v4
actions-rs/toolchain v1
actions/cache v3
.github/workflows/ci.yml
actions/checkout v4
actions-rs/toolchain v1
actions/cache v3
.github/workflows/coverage.yml
actions/checkout v4
codecov/codecov-action v3
.github/workflows/gh-pages.yml
actions/checkout v4
actions-rs/toolchain v1
jetli/wasm-pack-action v0.4.0
actions/cache v3
actions/setup-node v4
pnpm/action-setup v2.4.0
peaceiris/actions-gh-pages v3
benches/package.json
@types/benchmark ^2.1.1
@types/glob ^8.0.0
@vue/compiler-core ^3.2.19
benchmark ^2.1.4
glob ^10.0.0
microtime ^3.0.0
ts-node 10.9.2
typescript 5.3.3
napi/npm/android-arm64/package.json
node >= 10
napi/npm/darwin-arm64/package.json
node >= 10
napi/npm/darwin-x64/package.json
node >= 10
napi/npm/freebsd-x64/package.json
node >= 10
napi/npm/linux-arm-gnueabihf/package.json
node >= 10
napi/npm/linux-arm64-gnu/package.json
node >= 10
napi/npm/linux-arm64-musl/package.json
node >= 10
napi/npm/linux-x64-gnu/package.json
node >= 10
napi/npm/linux-x64-musl/package.json
node >= 10
napi/npm/win32-arm64-msvc/package.json
node >= 10
napi/npm/win32-ia32-msvc/package.json
node >= 10
napi/npm/win32-x64-msvc/package.json
node >= 10
napi/package.json
@node-rs/helper ^1.2.1
@napi-rs/cli 2.17.0
@types/node 20.11.8
ts-node 10.9.2
@vue/compiler-core 3.4.13
@vue/compiler-sfc 3.4.13
@typescript-eslint/eslint-plugin 6.18.1
@typescript-eslint/parser 6.18.1
ava 6.0.1
benny 3.7.1
chalk 5.3.0
eslint 8.56.0
eslint-config-prettier 9.1.0
eslint-plugin-import 2.29.1
eslint-plugin-prettier 5.1.3
eslint-plugin-sonarjs 0.23.0
npm-run-all 4.1.5
prettier 3.2.4
typescript 5.3.3
node >= 10
playground/package.json
vue 3.4.13
@babel/types 7.23.9
@vitejs/plugin-vue 5.0.3
typescript 5.3.3
vite 5.0.12
vue-tsc 1.8.27
The experimentation shows that rayon has at least 100us overhead for thread pool initialization.
However, most template can be compiled within 100us. The parallelization, at least in practice, does not pay off.
The example is the most complicated SFC in element-plus, el-table.vue. The compilation takes about 100us without thread pool.
But after the thread pool is introduced the compilation time comes to 200us+.
vue SFC file
<template v-if>
<div v-for="item in result">test {{item}}</div>
</template>
Root 0..78
Element 0..77
tag_name `template`
directive 10..14
name `if`
Element 18..65
tag_name `div`
directive 23..45
name `for`
value 29..45 `item in result`
Text 51..59 `test `
Interpolation 51..59 `item`
here text test
byte offset is 51..59, which is wrong,
the correct offset should be 46..51
Adding a pre-commit hook for
Currently Farm (https://github.com/farm-fe/farm) is working on compiling Vue project in Rust(see farm-fe/farm#125). If this project is not active, Farm is glad to develop this project, continue to make it production available
<template>
<my-component/>
<template>
in playground :
const _component_my_component = _resolveComponent(my-component)
should be :
const _component_my_component = _resolveComponent("my-component")
Currently Vue SFC parser is included in the "vue-compiler-core" crate. Would you like you separate and publish the parser as a crate? I hope it can only parser <template>
section, while other sections like <script>
and <style>
are kept as source text, leaving them to user to decide how to process them.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.