A demonstration of how the Svelte.js compiler works under the hood.
Download and install dependencies:
git clone https://github.com/joshnuss/micro-svelte-compiler
cd micro-svelte-compiler && yarn
This compiler has multiple stages:
- Parse the
.svelte
file and extract code from<script>
tags and build a list of non-<script>
tags. - Parse the code and determine props (anything with
export let ...
is a prop) - Parse the tags recursively and make an ordered list of nodes and event listeners
- Generate JavaScript code using props, nodes, listeners, and code from script tags
- Format the JavaScript code
- Print the result to
stdout
It uses similar dependencies to svelte.js (except for HTML parsing).
- acorn: Parses JavaScript text into AST.
- code-red: Generates JavaScript AST from template strings. Converts AST back to string.
- js-beautify: Formats JavaScript text.
- parse5: Parses HTML tags.
Say you have a .svelte
file like examples/basic.svelte
:
<script>
export let name;
function handleClick(e) {
e.preventDefault()
alert(`Hello ${name}!`)
}
</script>
<h1 class="snazzy" on:click=handleClick>Hello {name}!</h1>
Run the compiler on it:
npx msv examples/basic.svelte > examples/basic.js
It generates a JavaScript file that looks like this:
export default function component({ target, props }) {
let { name } = props;
function handleClick(e) {
e.preventDefault();
alert(`Hello ${name}!`);
}
let e0, t1, b2, t3;
return {
create() {
e0 = document.createElement("h1")
t1 = document.createTextNode("Hello ")
b2 = document.createTextNode(name)
t3 = document.createTextNode("!")
e0.setAttribute("class", "snazzy")
e0.addEventListener("click", handleClick)
},
mount() {
e0.appendChild(t1)
e0.appendChild(b2)
e0.appendChild(t3)
target.append(e0)
},
update(changes) {
if (changes.name) {
b2.data = name = changes.name
}
},
detach() {
target.removeChild(e0)
}
};
}
To host the component in the browser:
<script src="example/basic.js"></script>
<script>
// instantiate the component with a target node and some props
const c = component({target: document.body, props: {name: "Steve Wozniak"}})
// create DOM nodes
c.create()
// mount DOM nodes
c.mount()
// you can update props anytime:
c.update({name: "Elon Musk"})
// and cleanup the dom when it's no longer needed
c.detach()
</script>
MIT