Transcript
This transcript was autogenerated. To make changes, submit a PR.
Jamaica real
time feedback into the behavior of your distributed systems and
observing changes exceptions errors in real time
allows you to not only experiment with confidence, but respond
instantly to get things working again.
Code welcome
to Conf 42 Javascript. Today I'm going
to talk about build your own svelte, but before that,
let me share by mama myself I'm Lee
Hao again. I'm a frontend developer at Shopee.
I'm based in Singapore, but I'm born and raised in
Malaysia in a beautiful town called Bukit Murtajam.
So outside of work I do a bit of open source. I'm a svelte
maintainer, and if you'd like to follow me on social this
is my Twitter handle, but most importantly this is my YouTube
channel. I have a YouTube channel where I like to do contents
about frontend that I wish it was there when I first started out.
Well, when I first started out building web applications,
probably eight, nine years ago, I started with jQuery.
JQuery provides me utilities to select some elements and
do something with them. For example, when user interacts with the
page and the data changes, I use jquery to find the
elements and modify them directly. But this
gets messy quickly when applications get
more and more complex. Fast forward a few more years
I started to use React, which allows me to describe
my view as a function of data. This declarative
approach frees my mind to think about how to modify the elements,
but let the react library to figure that out.
The way how this works is that react takes a different snapshot
of the virtual Dom, comparing it and figuring out the
actions needed to update the actual dom.
This comes with a cost, and because react has no idea what
type of virtual dom there will be, whether it's this element,
or that element, or this event handler, that event handler.
So it has to have code to prepare for all eventuality.
For a very simple application, the react library
code may be overweight relative to the code you write,
but this of course is a trade off. Your code is no longer
as efficient as you would have it like if you write it in
jQuery, but you gain the ability to describe
as a more complex UI.
But what if you
can't write your component in a way
decoratively, like how you would in react,
but use a tool to turn it into optimized
JavaScript code? That how you would write in
jQuery. Well, that's when I started to learn
about Svelte.
Here's the svelte syntax. It's closely resemblance
of the HTML syntax and you can define variables
in a script text and use it in the HTML using the clear brackets.
You can define CSS in a style tag to
make changes of the variable. You can modify them directly
like this. Here we add a click event
listener called the decrement,
which when we click on the button we'll call the decrement function, which will
then modify the counter variable. And then you'll see that
the counter value that we use in the curly brackets over
here in a div will update immediately. Is that simple?
But how does that work? A lot of time I hear this
explanation where people say svelte is
a compiler based framework. Takes a code.
You write, analyze and compile it into JavaScript. So you can
do a lot of magical things that you can do in JavaScript.
But still, how does it work?
I'm a big fan of the idea getting your hands dirty,
learning by building. And I probably learn a lot
from content like this. Say for example writing a library using
jquery. Build your own react.
But what about build your own svelte?
I haven't find any content about that yet. So today we're going to
going to do that and figure anything out together.
I do realize that this may be the first time for some of you to
hear about svelte. It's okay. I have a series of YouTube tutorials
teaching about Svelte. You can visit them my YouTube channel,
watch them later. But today, instead of talking about how to use
svelte, I'm going to talk about how to create spelt,
how to create a compiler based framework like spelt or quick
or Astro, meta frameworks like Astro, and we're going to hear
about them.
And today I'm going to talk about how you can create
a compiler. The word compiler
sounds very scary to me when I first started to get
figuring this out. Well,
don't worry, we are here together to learn this
min general this is a breakdown of what a compiler do.
It takes your code, parse it, analyze it,
and finally generate an output. Let's take a look closer
look at each of this step. First,
when we say the compiler process your code, it takes your code
and generates a representation of your code that
probably looks like a tree structure. And we call this
an abstract syntax tree or ast
for shots. It is called abstract because it contains the
abstract structure of a code as compiler to concrete
syntax tree, which contains all the concrete
detail such as where is the semicolon, where is the parenthesis and
things like that. So for abstract syntax tree just contains
the semantic meaning of insight as a tree.
And then the compiler analyzes this tree,
the code through this tree. What this means is that irrecursively
going through every code of your ast, trying to gather information such
as maybe what are the variables being declared, what are the
variables being used, and what variables will be changed
and so forth. And armed with that information,
the compiler is then able to generate a more optimized code.
So today, with time permits, we're going to implement a very,
very simplified version of spelt.
This will be our compiles that we are going to compile.
Any feature that you see on here will be used.
Any feature that you don't see in this component will
not be implemented. This is the example
of the counter component that we just saw where you
have two buttons, one click to decrement, one click to increment,
and you have a div that contains the counter.
Right? So here, let's take a look at my
project setup. So here I have
prepared with you with the code.
Let me zoom that in a bit more. So here
I have a app, dots felt, which is the counter component
that you just saw. Sorry, I think. Let me clean
this up a bit different. I think so.
Okay, this is exactly the counter component that you just saw.
And later on I will compile this
app svelte into the app js file in this
folder. Okay? And then you see the index HTML.
This is where we are going to import this app js that we will be
generating later on. And we're going to use this to
create amount our component index
JS is where our compiler code will be. So here I've
already written the instructions, right.
So we will read the file into
this content, we're going to parse it into ast. We're going to analyze the AST
to get the analysis. I'm going to use the AST and the analysis to
generate a Javascript code. I'm going to write that file into app js
in the end. So these three functions is what we're going to
implement.
So the first thing we're going to look at is this.
Well we keep mentioning that the svelte compiler will compile this into an optimized
Javascript. But how would that Javascript look like?
Since we are creating a simplified version of svelte, let's design our simplified
version of the svelte output.
First, the simplest code for creating a button like this
is to have these instructions
where we create element going to add event listeners click
and then the decrement function, we're going to append this
button to the parent and to destroy. We are
going to call the remove event listeners to clean up as well as remove child
to remove this element from the parent. So here
we need some function to call the crit and destroy instructions
separately. So let's direct them in an object method like this
one. And also we want to be able to create multiple
counter compiles. So let's have it as a function that
returns the lifecycle object so that we can keep calling
app to create multiple instances of this component.
And then we can call the create to mount
and pass in the target where we are going to mount our component.
Wait, oops, I think I forgot that the button needs
to have some text. Right. So here I'm going to add a few more
lines of code. Here we're going to create a text node. I'm going to append
the text node into the button and we can keep doing this
and this and this and we keep adding code
to build up the component.
Wait, but wait a minute. I think the counter expression is
dynamic. So we need one more way to basically up call to
updates the value updates the content of
the text node. So we're going to create a lifecycle called
updates where we're going to pass in a parameter called change which is
taking min as an array that can contain what are the
variables that will change and then we will change it by setting the data
to the updated value. So here is how we're going
to call this function. And the increment function will probably will
insert a line called lifecycle update. The counter
right here. We're going to probably will do some analysis to figure that
out. Figure out if
we're going to change the counter and if counter will change, we're going to figure
out that where it will be changing and we insert
the lifecycle updates method over there.
That's why the analysis step is very important because it let
us know to know which variables will change.
Okay, but you may ask me one question.
The way I visualize just now, right. We step
through and visualize. This seems very straightforward
from your naked eye. But how do you
actually write the code to do that? Right, because in
essence the code that you see the eye of
a computer is just a bunch of characters.
It's a string. So how do you take
this string and then figure out what other elements are
there? Well, that's why we need to parse the
code into ast. That will be much clearer if you
compare the steps using ast.
So let me walk through the steps that we saw just now,
but with the ast as we go down,
we realize that actually traversing each element is like traversing through
the each node in the ast.
So that's why it's much simpler if you can able to write
a parser to parse the code, right? So now
that begs the question, how do you pass a string into ast?
Well, Min, all things in programming there's always a technique to do it,
and today I'm going to show you how. So first of all, before we
do that, we need to describe how our code should look like.
The way to describe it. We're going to use this thing called a syntax
notation. This is like the design document, like the PRD,
but describing how your syntax should look like.
We need this before we can even start writing our parser.
There are various syntax notation. It could be a real
root diagrams. You can have the Becker's north form.
Well, in this example of the Becker's north form I'm going to show you,
it describes how a JSON object syntax should look like.
So I guess as a JavaScript developer, you are very familiar
with how a JSON object should look like, right? A JSON object could
be either a open and curly brackets like this,
or open brackets, a property list and a
closed brackets, right? So the first one is for an
empty object, this one is for object with some key values.
But what's the syntax of property list? Well, we can define it.
Again, the syntax of a property list can be a property
or a property list with a comma and
then a property. So you can see the recursiveness in terms of
how you can define the syntax. So now what is the property?
Well, the property can be a string
and then a colon, the colon string, and then a
value, right? And then you can keep doing this,
define how you look like as a syntax of a string,
and what's the syntax of the value? But that's not what we're going to do
here today we're going to talk about syntax of svelte.
So here's how I'm going to define the syntax of svelte.
Say, syntax of svelte is a fragments,
which is made up of a fragment
or multiple fragments without any space with
the fragment. So fragment itself can
be a script, an element, or expressions or
text. So now we're going to define the syntax of a script.
Well, for the script is the brackets,
angle brackets, S-C-R-I-P-T angle brackets,
and then with some Javascript and then angle brackets
again, S-C-R-I-P-T angle brackets. So this is a syntax
for the script. How about elements? Well,
elements is a angle brackets, the name of the tag,
tag names, attribute lists and angle brackets,
fragments, angle brackets, fragments, tag name
and angle brackets. We can keep doing this for each
of them, right? So for example, attributes is an attribute name with
equal curly brackets and then Javascript and then curly brackets.
Keep doing all this. Okay, so now
after we have this, now it's time to implement our
parser. Let me close this. Okay,
so now let's write some basic structure for our parser.
Going to type real fast over here. Wow. So the
thing is, I'm going to here create a few helper functions I'm going
to create a few helper functions for each type of the node that we are
going to pass. So just now we see that we have fragments,
fragment, Javascript element attribute. Yeah, so we're going to just create
one function for each of the type, right?
So here this structure, you see that we're going to create an ast,
an object that represents the tree itself
and call the past fragments to give us the ast. And here
I'm going to define a variable called I. But what is I?
So if you see I, I is actually a pointer.
It will be a pointer that points to
the character we have in the string. And the core idea
of a parser is to match the characters where I is currently pointing
at. Like here we are pointing min the angle brackets,
and based on the syntax rule we can decide
whether to advance or to read
the value out from where I is pointing at.
So we have our rules and we're going to figure out how to advance and
match the characters based on where I is pointing at.
So I have this page that shows you the syntax and let's get
back to the code. So the first syntax that we see is
fragments, which can be one fragment or multiple fragments.
So before we actually go that, right, I think let's
write some helper function for us to
advance, match, advanced and read value. We're going
to have one helper function for each. So to match
the value I'm going to create the match function,
which basically gives me a boolean value to tell me whether the
I that's pointing at matches the value that we're going
to call it. Right? So we're going to slice that string out and
compare whether we match where I pointing
at is matching the value. The string that we're going to pass min
and the next one is trying to advance I, right?
So I'm going to call this function called it.
And the way how it works is that,
for example, if I try to pass an
attribute over here, for example,
after I reach the attribute name, I know that the
next thing I need to have
is the equal and curly brackets.
I try to match this, I will match this and
if it matches then I will advance my eye, right?
And if it does not match, then it's a syntax error,
right? So basically we don't really care what symbol is this, we just
want to match and then advance I and if it does not
match, we're going to throw a syntax error and this is what exactly I'm doing,
right, I've matched an advance. If not, I'm going to throw
a syntax error, then lastly is trying to read the
value out, right? So this case will be the case where we're going to use
for reading value out, say the attribute name, reading the
tag name or the attribute value, right? So here
I'm going to create this function called read while matching. Basically it takes
min a regular expressions, and as long as the regular expressions
matches the content where I is pointing at, then we'll keep advancing
I and then we're going to return whatever we have read
so far while advancing I so the first thing is the
fragments, right? So fragments is going to be
an array and we are going to keep calling the parse fragments
to read out the fragments and going to push it into the array.
And this is the parse fragments.
So for fragment itself we have seen here that
it will be either a script element, expressions or text.
So I'm going to rely on these functions to
help me. Right, so you get a script element, expression or text.
Well now let's go to the more difficult one,
right, script, how do you pass a Javascript? Let's take a look. So for
script we're going to match this string, right, SdRI PT with
angle brackets, and I'm going to keep reading anything until we
hit the angle bracket sri pt so
this is how we're going to parse the Javascript. So here
I'm going to match script and then I'm going to edit this so
that we can advance, and then later on it will just keep
reading contents until we find the angle brackets.
SRi pt so this is the code that we're going to
take it out. And of course today I'm not going to spend my time to
figure out how we can write a JavaScript parcel. We can actually use a
library to do that for me. So I'm going
to use import set library,
which is called econt. Okay, I'm going to parse it
and then I'm going to advance my eye and also eat away
the closing JavaScript tags. And that's it.
So for parse element, let's see.
So for parse element we're going to have angle brackets, the tag
name attribute list, angle brackets and then pass
fragments, again, angle bracket slash and then eat away
this tag name, right? So it's like matching read
while matching parse attribute,
list it, this pass fragments
at the angle bracket, slash it, the tag name
as well as angle brackets. Let's try to do that.
Right. First we're going to match edit and
I'm going to read while matching and I'm going to pass and then yeah,
so basically how we see
the syntax rule, how we translate it and how we just type it out.
So for children we're going to call past fragments, but the past fragments
that we have over here will keep reading
until we hit the end of the contents.
But the past fragment here I'm going to use is until we hit
the closing tag, right? So maybe we want to have a different condition. So we're
going to create a parameter called condition, replace it,
and so here we're going to keep matching until we'll match the end tag,
right? So here on top we're going to just keep reading until
we hit the end of the content. So we have
passed elements, let's go to pass attribute list. This is
kind of similar to pass fragments. So going to
have an attribute array and then skip white space, right? So in
each attribute we're going to have one white space.
So the white space can be more one character white space, multiple character
white space. So how we can do that is actually we're going to reuse
some of the utilities that we already have, like the read while matching,
basically skipping white space will be like reading white spaces
character, but then we just ignore whatever we read out so far.
Okay, so now, next thing. So now we're going to
keep reading attribute until we hit the angle brackets,
which tells us that we are at the end of this opening
tag. So while we are not
matching, we're going to call pass attributes and then we're going to keep looping
that. So for pass attributes here,
if you see, we will be keep reading whatever
it is until it hits the equal sign and then we're going to eat these
two characters until it hits
the color brackets and then we're going to eat the color brackets so
here I'm going to read while matching, type out real quick,
right, it's it. And so for pass expressions,
if you see here, we're going to eat curly brackets,
some JavaScript and curly brackets. So we're going to match curly
brackets, eat that, parse JavaScript and it another closing curly
brackets for text. Basically it
will be anything that is not script elements or expressions.
So basically we can keep reading any value until we hit
the angle brackets or the curly brackets.
So we're going to use the read while matching,
and then we're going to trim away some of the empty spaces.
So if you take a look over here, the code from here to
here, there are some new lines, characters, but we're just going to make
things easy. We're just going to skip and don't see them. So as long
as the text is maybe after we trim is just content full
of anti strings, then white spaces, then we're just going to ignore it
and only have the code for text that
has actual values. So finally we're going to
call Parse Javascript here, we're going to use acon to help us to do
that. Okay? And I think that's it.
Right, so let's see our result. So here
I'm going to call my,
hold on, let me see here we can pass,
and then since we ever have the analysis and generate, let's comment
them out. So I'm going to write the code,
the ast that we have into a JSON
file est. Okay,
I'm going to run this.
And here we see basically our est
that we do. Yay. Okay,
so here we have our, let's collapse
this. Here we have our HTML, which is the ast of the
template, right? So here if you look side by side,
you will see that we have the elements,
which is the button over here, and then you have attributes,
which contains name on click and the value which is JavaScript
est. And then next we have the children, which is the text
code. It's called decrement. So next one we have this
element called div children. And yeah,
basically we have everything now. Okay,
so I think that's it for parsing. Yay. It's not that hard,
right? You can do that. So I think let's continue
when writing the next part, which is to do analysis.
So to analyze our code, this is our JavaScript code.
If you just look at it, you probably can tell that there will be three
variables, right? These are the variables that be top level and be able
to be used in your template. And you also
can tell from the eye because I believe you are
experienced developer can probably tell that
here we are modifying counter,
right, because the variable names is the same,
but it's not that straightforward. It's not just about variable names because
if you look at the code right here you
can probably say that, yeah, you're right, because although the counter
variable has the same variable name, but this is modifying the counter being
declared locally and not modifying the counter variable up
there, right? And this is because of this concept called
a shopee, right. Each of this scope you can declare a variable,
define a variable, and then if you are
assessing the variable, you'll be looking from the inner scope
before we look up to the outer scope, right? So here
there is three shopee, but you may ask me how
do I know, how do I tell from Li Hau Tan tell
there's multiple scope, but how do you able
to tell that with your code?
Well, it will be much easier if you have the ast, right?
So this is the ast for the Javascript and you try to color code
the scope, you'll see that a scope
is like a subtree of your est.
So the root of that subtree is a node
that creates a new scope. And today
we're not going to figure
out how to write the code to analyze the shopee. I'm going to use a
library called periscopic to do that for us.
Okay, so I'm going to import this library.
No, I think let me walk through one more.
So we're going to have this periscopic. What it does is that you can analyze
the JavaScript est and it returns you the map, the globals
and the scope. Okay, so the
scope is the root shopee and then the map
is actually a mapping of the code that creates scope and the
scope itself. So in this case if you have three
code, then the map will have three entries,
right? The keys will be this code, this node and this node,
and then the value will be the scope that the
root scope, the two child scope that it creates,
the scope one and scope two. Okay, so with
that I think we probably should start writing
some code in our analysis. So here,
let's figure out some structure.
First is what we're going to analyze. So we're going to have the object
called results. I'm going to store things like what we're going to analyze over here.
So we have three things, right? The variables, what are variables and what are the
variables will change and what are the variables will be used in a template.
So the first thing is that analysis.
Are we going to call it periscopic to analyze the scope for
me? So here,
based on what is defined in the root scope, we can
declare in root scope we can tell that these are the variables that you can
use, right? And then we're going to keep the root scope and
the map in the results so that we can use them later on as well.
So we need to figure out what is the current scope. I'm going to use
a library to then traverse
through the tree. This library called Esri Walker,
it has two callbacks. One is the enter we will call
whenever we enter a node and then we will call whenever we are leaving the
node. So how this Esri Walker works is
that it uses the daffer search. So it will
traverse the tree in a daffer search manner.
And you see that we're going to figure out what is the scope,
right? And because of this deferred search
manner, we can't actually able to tell what is the current scope
because whenever it looks, does the
deferred search traversal whenever it enters its node
that is creating a new shopee.
We can find this by looking at the map that returns from the periscopic.
Whenever we found a map we say okay, now this
is a node that creates scope. Then we'll set the current scope as the
scope that this code creates. And then we step through,
therefore search and keep traversing through the inner child nodes.
And then as we come back up and we encounter
this node again, realize that, okay, now we're exiting this scope,
we're going back to the parent scope, right? So when we exit, we'll reset
back this current scope to the parent scope, right? So here
whenever we encounter a node that has
in the map, then we can set the current shopee as the
scope that we're being created by the nodes. And if we encounter
a node when we're leaving, then we update the current scope as the parent scope.
So now with the scope, now we can know, now we can
find the variables, whether the variables is being declared in
the scope. We can use the current scope to figure out where this variable
is being declared. So here we're going to
check, I think first is
we need to figure out what are the
code that will make changes, right? So here we use
a tool called the est Explorer.
I just pasted the code in here so you can
see over here, if I hover over here,
that you will see that this is an update
expressions and then the variable itself is
in the argument name. This is the
variable name. Okay,
so we need to check if the node type is update expressions
and we ask the current scope, which scope that we declare
this argument name, this variable name.
And if this is being declared in the root scope,
then we know we encounter something that's changed.
Then we're going to say result will change. We'll add this thing in.
Okay, and I think that's it for analyzing
what variables will change. The next thing I want to analyze
also is what are the variables that will be used in a template. So here
what we can do is we're going to traverse through the ast
that we just created, the fragments.
And then over here we are going to look at two things, right?
So first is that if it's being used as the attribute value,
then this is the variable that we just assume this
is being used in a template. And over here also if this
variable is in an expression, we are going to say it's being
used in a template. So encounter,
depending on which type of the frank type we encounter, if it's an
element we just keep traversing its children and its
attribute. And if
it's an attribute, then we're going to say attribute value is
being used in a template. And if it's expression, I'm going
to say the expression value itself
will be used in the templates.
And I think that is it
for analyzing. Let's try and run our code.
This time around I'm going to comment way analysis
and generate MJ's console out analysis.
So let me run the code and you'll see this is the analysis
results on the variables change and be used
in templates. And if I come over here and
try and change something, for example, if I remove this too,
just completely remove it, then you'll see that,
hold on.
Then you'll see that variable
that we use in the template is only decrement,
right? And if I try to come
over here and say, for example, remove this
variable, then you'll see that the variables we
have left is counter and decrement.
And over here if I try to say let
counter equals to zero, then we know that this counter is actually referring
to discounter rather than outer one. And run analysis again.
You see that world change is now an empty set.
We didn't change any variables. Okay, so let
me reset this back and then I
think it's time to go back to our code.
So now we're able to analyze and
parse and then analyze our code. I think the
next thing is we're going to figure out how we can generate
the code.
So the idea of generating each code will be
as simple as going through each node and then figure out
what are the instructions that we need to insert for
creating and destroying the elements. So we're going to go through each
of the element and figure out what are the instructions needed.
So let's go back to our code. So here I'm going to
write something, right? So for generate, going to create a few arrays
which this will containing the instructions for create, update and destroy,
and then also the list of variables that we use.
So here the code will look something like this.
So here, min, create, update, destroy. We're going
to join the instructions over min, each of them
and then also for
these variables that we have, so need to declare them. So here is
how I'm going to declare using the let the variable
name. Okay, so here if I try to run
this now, you'll see
that I have a very basic structure.
Now we have nothing. So now let's continue to write
our code. So here I'm
going to create a function called traverse. I'm going to traverse each type of the
node. So for element, what we have
here is we have instructions to create element
and then we also call traverse for the attributes and the
children.
And then we need to append a child to the parent as well as
to remove child in the parent in the destroy methods,
right? So these are the things, the next element
we're going to do is the text. So for
text, if you look here, next thing for
text we want to need is to document a create text node for the text
content and then we append to the parent.
Okay, so here we're going to create the text node,
we're going to push this variable name and then we're going
to say we're going to create
text code and then we're going to use to append the parent with the append
child. Next thing we have is attributes.
So for attributes we are going to just handle the
on click event listeners. So for that we're going to have two instructions,
one in a create array when instructions to
add event listeners the events name and the variable.
And then for destroy instructions we're going to call remove event listeners the
name of the event and then the variable. So this decrement comes directly
from the attribute value and then the value
of the listener compiles directly from the attribute
name where we just remove the first three characters.
Okay, so here I'm going to do that if
it starts with the on event listeners. So we're going to get event
name right, remove the first three characters, event handler.
We just assume that the variable itself is an event handler and
then we're going to basically add instruction to create and into destroy
and that's it. So lastly we have expressions.
So expressions like
this, we're going to just treat it as if it is just a text
note. And then one thing we're going to do is we're going to analyze and
we're going to use analysis to figure out whether this
variable like the counter will change. If it will.
Then we're going to include these conditions here to basically
call to update the text value with the latest value.
So here I am going to create this
text code first,
right. And then I'm going to use the analysis basically to check if
we have the world change. Then we are going to
new instructions in the updates call.
Okay, I think that's it,
right. So I think we will have one more thing which
is to call traverse the fragment,
right. So let's save this and let's try and run our code.
So here is our code right now,
okay. Basically we have all the structures, it looks
quite good, really you should proud of yourself to
be progressing so far. So I
think one thing we're still missing is that this variable like decrements, these are not
defined yet, right. Basically the code inside this Javascript over
here, we still haven't figured a way to insert
them, right. So we need to figure a way to basically add
this lifecycle update over here
in all the update expressions. So to do
that we
are going to paste in the code that we have earlier on,
basically is where we use the,
where we try to figure any variables that will change.
Right over here I'm going to make some changes. Basically we
are going to also check whether
the variable, not just we know that it will change,
we'll also check whether it will actually be used in a template. If not,
we're not going to add the lifecycle
updates function, right? So if we have this used in
templates then we are going to insert this instruction
for lifecycle updates. Okay?
Yeah, this one, just assume that it works. I'm not
going to explain too much into this one. So by now let's
see, I think we need to, after we change the ast, we need to
come over here and insert this code. So we're going to use
a library called escode gen, basically what turns Javascript
into a string. And I'm going to turn that ast into the
string since the whole thing we generate is a string. Right. So we're
going to turn that into a string and then
insert a line over here and I think that's
kind of it. Right. Let's try and run our code and see what we get.
Let's fresh this. So here we basically have this
instructions, looks promising and we have
the lifecycle updates. And in the lifecycle update you have
this. And let's try and run this in a browser,
shall we? So here I'm going to start the server,
I'm going to run this server and this is the compiles
that you see, right. And this is the magical
moment. I'm going to click on the decrements and
it works. Yay. And increments, yes, it works
as well. Whoa. Okay, so we
kind of managed to write all this within a
short period of time. And so you see that this is
how a compiler is being written, right?
And to show you, to demonstrate to you that
this compiler writes is an optimized,
generates an optimized javascript code and actually uses what
we analyze, let's try to make some changes in our component
and see what is being generated. The first thing is that what
if I do not change anything in the counter,
right. For example, we have a variable called counter right here and we
try and modify the local variable. So basically this counter
is not going to change what will happen trying to
build this. You will see that first
of all, I do not insert the lifecycle update,
and secondly, in the lifecycle update method here is empty.
So we don't need to generate extra code. If we don't really
need it, right? We are not going to change the counter, then we don't have
to need the update function, right? Of course you can do it
much better by removing this function totally because
you don't even need it. Yeah, we should do that.
So maybe you can try doing that yourself. Right?
So what if, say for example, we're not changing
it this way, but we are not going to have this
counter variable, right? We can still click on counter,
counter increment and decrement, but we're not going to show that on
the template. We're going to use the counterparble in the template.
Guess what happens?
This is what happens. So first of all,
again, we don't have that Div and the updates, we don't have
the instructions to do those things. And secondly,
this knows that we can still update the
counter variable and we can still console log to see the updated value.
But we no longer needed to call the lifecycle updates because we
are not using that value in the template.
So there's no need to call the updates at all
because there's no dynamic expressions over
here. So you can see that
we are actually create an optimized Javascript based on
what we analyze. And basically that's what svelte do.
Okay, so some summary.
We figure out how to write a compiler within
a span of, I think, I don't know how long
we have spent, maybe 40, 50 minutes. Right?
So if you can type really fast, that's how
long you need to take to write a compiler.
Right, so what is a compiler? This is the
compilation step. We parse our code into an ast and
then we do some analyzing to get an analysis, and then
we use the analysis and ast to generate the JavaScript codes.
Right. So here of course we don't have time or we don't really
have a space for do questions, but feel free to find
me on Twitter or on YouTube. So this is my YouTube channel
and all the codes that you saw just now is available on
GitHub called Minisvelt. Here you can find
this. And actually I have also actually
recorded some of this talk, some part of this content and
subsequent following up content in my YouTube channel. You can go
and watch that. It will be
part of this build your own svelte series hold
on, series where you will
see that you'll
find a series. Hold on,
let me get the playlist for you.
Right, so this is the build your own svelte
playlist. Right now we have three and I intend
to add a few more follow ups on how you can make it it
more complete, how you can add reactive declarations that you have min
spelt, how you can do it on the server side rendering and things like
that. So do subscribe to my YouTube channel and I
shall see you and hope you enjoy the rest of the conference.
Bye.