 All right, hi. Wow, pretty huge. Anyway, so I'm Sebastian, and I've got the presentation stuff, the code, the demo, whatever, all up in my GitLab repository if you are interested in that. So I'll be talking about Babel. And it's not a very long talk, but just to give you an idea, I'm going to talk about how to make Babel plugins, generally. So talk a little bit about what Babel is, sort of how what compilers are, kind of learned a little bit about that, different stages. And then we're going to code a couple of demos, see what we can do with these things. And then maybe I'll show what I've been doing with that beyond that. OK, so let's start. So we can use Babel to do code mods, which is like modifying code. So you kind of take code and turn it into other code. It's a little bit meta. I didn't know anything about compilers. I've never done computer science or anything like that, just like the guy who created Babel. He's also called Sebastian, so we've got two things in common. So yeah, there's this awesome project called Babel, which I'm sure everyone knows about, nothing new. Everyone uses it to transpile their beautiful ES6 code into stuff that actually runs on the platforms that we're targeting. So if you're not familiar with Babel, it basically takes future code that is supposed to work and turns into code that currently works in ancient systems like state-of-the-art browsers and V8 and stuff like that. Now, the basics of Babel is like any other compiler that it takes code and turns it into what's called an ASD, an abstract syntax tree. That's a weird theory thing. You then transform your ASD to a different ASD. Who knows what that means? And then it generates the ASD into code again or into a source map. So there's the three general stages. Each of these is very modular with Babel. You can actually modify through plugins what happens at the parse stage, the transform stage, and the generation stage. I'm actually going to talk about mainly the stuff that we can do with plugins at the transformation stage. That's what everyone really does. There's a little bit about the parsing that I'll go into because it's kind of interesting to see how it works. And you could also extend that if you want to. So the parsing takes the source code, turns it to tokens. So then turns those tokens into a tree of nodes. So the output is that ASD. So it takes code and turns it in ASD. The two stages are that it takes, what's called Babylon. So it does this lexical analysis to turn the source code into tokens. So basically think of like in English there would be, you take a sentence and you take every word and you sort of mark it as a word, right? Without any meaning. So it just like chops it into different words. That's kind of what the source code does. It takes every little chunk of the code and turns it into a chunk and it says that this is a chunk. That's about it. It's very, very simple. It's like a flat list of chunks of code. The second stage that it does, to turn it into an actually meaningful tree, the ASD, then it's where it's gonna figure out like, oh, this is actually an assignment or this is an operator and there's like two operands. And it'll figure out sort of what the code means. And then it gives you that as a nice tree. And so we can see what that kind of looks like with this awesome tool called ASD Explorer. If I got a wifi, let's see if we can load that. It's basically like a DOM for your code. So here's a generic example where we see a little bit of code on the left-hand side and we see the automatically generated ASD. So if you're using ASDs, you'll find that there's lots of different parsers. And the one that we're talking about is Babylon, specifically version six. That's the latest one with Babel. So the Babylon six parser is slightly different. They're all gonna be more or less the same but you'll see a bunch of information here that sort of describes the source code that you're looking at. The top level, that would be like your HTML, your document or something, right? In ASD, that's gonna be a file. And you step into your program and inside your program, you've got all the different parts of your code. Now, just for clarity, we can turn off like empty keys and location data just to collapse. Basically, you don't need to know like what character of the source code we started at. But here we can see the code on the left-hand side and when you click on it, any part is very nice. It takes you to the exact node in the tree that that represents. So in this case, this little string here is a string literal node. Every node has a type and that's it. So beyond the type, it depends on what type it is, right? So think of it as different classes and they all extend from this node base class and this has a type. And then, like for example, a string literal will have a value and maybe a raw value and things like that tucked away. But you generally don't need these other ones. And when you're transforming the tree anyway. So this is a nice little tool ASD Explorer. If you're playing with Babel's plugins and stuff like that, this is definitely gonna come in handy. But you can see how, for example, different parts work. So you zoom out a little bit. You see there's a call expression and it's highlighted on the left-hand side. There's a member expression. The member expression has two properties, an object identifier here, this console and then another identifier log and things like that. It's very intuitive. And if you're familiar with web, of course, you can use similar APIs to traverse the node, to traverse the tree, to create nodes, to remove, replace and manipulate them. And that's the API that Babel really gives you and Babelon actually gives you and a bunch of helpers on top of that. So let's see what we can do with that. Okay, so that was basically the parsing to turn it into this tree and then this is what we get. So the next stage is gonna be that we transform it, like I said, we're gonna do stuff with the code. So you can imagine that there's lots of things that we may do and I'll show some examples to take our input source, manipulate a little bit using these APIs and then end up with a different tree. And the reason why you wanna do that is because in the next stage, it'll go and generate the output source code and the output source maps. So you don't wanna deal with that manually. It would be incredibly tricky string manipulation. So you wanna deal with just a tree. It takes another tree and then it generates a source map. It'll generate the output, things like that. So all right, let's see what we can do with that. So the first thing, I'm gonna sort of introduce a little bit of basic concepts as well as the libraries that make up the Babel ecosystem. Babel is actually one giant repository. It's a monorepository to manage it. They actually made a tool to manage monorepositories. If you deal with it on GitHub, it's pretty overwhelming because all the issues with all of these sub-projects are in the same repository. All the source code is all in one giant repository except for Babylon, which is somehow slightly separate. Anyway, so Babeltroverse is the first one and that's basically gonna be how we, think of it like a jQuery, right? You're kind of like running through our query selector. Like you're just running through the entire tree and picking things off that you wanna deal with. You don't wanna deal with the entire tree. It's just gonna give you little sub-trees, like little branches off the tree that you can then work with. And here's a little example where we just log for every, what do we look at? We're looking for string literals, okay? And we're gonna log whenever we find a string. So the code goes very simple. You import the transform function from Babelcore and you pass it a little bit of code as a string. So you can imagine reading from a file, passing it into transform, and then the second argument is gonna be basically your BabelRC file. So if you're familiar with Babel, if you're familiar with the BabelRC file, we specify the presets and the plugins that you wanna use, right? Now, if you're calling it from the API, you can just stick in the JSON representation of that and you can do something else, which is the plugins, there's typically an array of little strings. You can stick in an object here that has this visitor property. And the visitor property is gonna be a function that is named, or is gonna be a function that's named after the type of node that you wanna work with. So there's like dozens, hundreds of these different types of nodes and you would specify which one you wanna deal with and then get a callback every time that is encountered in the tree. So you kind of like fire and forget, okay? You just give this to Babel and it'll call you back and say, hey, I found a string literal or I found a member expression or I found this or that. And then you didn't work with it, manipulate the tree and then it hands off again and then it continues on within Babel. So you can give it tons and tons of these plugins and that's effectively how the presets work. So if you do a preset like ES 2017 or Latest or something or React, it's basically just loading like 10 or 20 plugins and each one does like a tiniest little thing. A lot of them are just a few lines long and they're very, very powerful that way. One caveat is that you don't really control the order of execution. So it could be that one plugin modifies something that you're expecting but it only does it at a later stage by hooking into a different type and then modifying it. So you kind of end up with a little bit of issues that in my work I had to work around with by running the Babel transformation multiple times with different sort of delicately set up structured sequences of plugins or sequences of presets. So be aware of that. But anyway, let's see what we can do. But if we actually run this, let's see if I have a terminal here. Wonderful, how convenient. So one of the demos, okay. So if we just run this now, I'm gonna run this with Babel node so that I don't have to transpire separately. What is this one? Traverse. Yeah, there we go. So this one here, it is going to log three times that I found a string. And that's sort of what we expected. We have three strings here. So notice that this is the source code right here and it has a string literal, a string literal and another string literal. So it doesn't execute anything. It doesn't like combine these and do all clever things with it. It'll really figure out exactly what in the tree each of these things are and call back and it will just log, okay, we found three strings here and this is a very, very basic stuff. But what could we actually do with this, right? And what we could do with this visitor, right? With the nodes that we're dealing with in our plugin. So we can make a very simple linter. So here's like a 10 lines or so and this is a JavaScript linter, right? It's not a very useful one, but it's technically a linter. So let's say that we run this code. What's it gonna do? It's gonna take this different piece of input source code. So we have a var foo equals one to three and var bar equals four, five, six. And this is an uppercase foo and I don't like that in my code. If I have a variable that's not a class definition, I don't want it to start with an uppercase variable. So I have a little plugin that I can create here for every variable declarator. I'm gonna inspect its name and check the first character and then see if it is an uppercase character and then give you a warning. So I could run this in my infium test and always get a warning when something like this slips into my code, right? So I could run this and very simply using this plugin, I can say, okay, now I'm gonna pick out that this variable foo begins with an uppercase letter. So it's a very, very simple way to start creating useful things for yourself, right? And this is effectively what things like, you know, standard or ESLint, this is sort of how they work. They all use one parser or another to generate an AST and then have a lot of these little rules that just scan through the tree and issue warnings and then have a little warning reporting system and that's your linter basically, right? This is sort of how they all work. So this is very easy to build these kind of things. Another thing is gonna be the battle types library. This gives you validators and builders which are kind of like very useful helper functions to inspect nodes in the tree in a very clean way. So you don't have to look at the type property and compare it to some list that you have or something. You can just go, you know, types dot is a string literal and then you give it a node and maybe you can pass it some options like does it actually contain this property to be equal to that? You can also create your own types this way. You can create your own nodes that way. So if you're generating new, you know, again, the analogy to the DOM would be you create, you do a new element, you create a new element. This would be you creating a new node with the types library. This is also the reference for figuring out what types there are in battle because there's loads and it gets really tricky sometimes to figure out exactly what you need. A lot of types also can be used interchangeably. So they might all be an expression even if it's a member expression, right? So if something is expecting an expression, you have to make sure that they sort of matches. But so yeah, this is very useful link if you're getting to this stuff. Then a use case of this, for example, like what do we do with all these types and these builders and these validators, right? We could build a little transpiler. So we can take one form of code that contains an alert and let's say that we don't like alerts. We just want to automatically turn all the alerts in our source code into console logs to not, you know, annoy the user, right? This is a simple way to do that. We can have a little plugin that notice how now it's no longer just an object. It's actually a callback function. When you specify a callback function, it feeds in the types, so you don't have to import it yourself. So we get the types as t and we check all the call expressions, which is like a function getting invoked, right? And you just, you know, you check like, is the, whether the callee property, so basically how you figure out what the path and all these nodes and all that stuff, you just take some source code, drop it into ASD Explorer and click around and say, okay, oh, I'm looking at the node that callee. Then you pass it in and it needs to be an identifier. Oh, and it needs to have a name called alert. So you kind of like, the way I work with this stuff is really just look at the different references, the different documentations and use the AXD Explorer and sort of like click, click, click until you get it and then, okay, you're done. It's a little bit insane to keep all these things on your head, so this is a very trial and error kind of approach. But anyway, I just, you know, you would look at the callee and say, if it matches the, if it's an identifier and it has a name of alert, so if we found a function being called, that's called alert, then we're gonna replace the path callee with a member expression and the member expression is console.log, right? So that's sort of how you specify that and to generate a new node in the ASD and then replace the existing node with that node, right? So this is a very simple way to do that. Let's see if it runs. And we didn't know what it's called. What if I traverse and change builder? Wait, I don't know which one this is. Excuse me. Yeah, this one here, okay. All right, so it changed my alert hello world into a console.log hello world. So the output source code, I can now write that to a file and feed it to my browser. So this could be a build step to transpile stuff. So this is a mini-battle transpilation plugin. So I don't know, this is not the most useful thing as little, you know, examples like this, but you know, you add all these things up and it becomes super, super useful. Lastly, another kind of important concept in the babel context, I'm guessing this is the same everywhere for other compilers, is scopes. So with scopes, it helps you figure out whether like variables are gonna be clashing with the variables in that context. So this is normally a very complicated thing in JavaScript or any language really and it takes care of that completely. So you can simply rename a variable. So I can rename food to bar. I give in var food equals one to three and I'm gonna rename it var bar, one to three. Or I can generate variable names like basically making sure, I guaranteeing that they're not gonna collide with anything else. A use case for this would be to minify things. So if you have something with very long variable names, I can rename them to something very short. So I'm not gonna bother running this. Basically, this is how minifiers also work. They kind of figure out, you know, variable names that can be removed because they're not exposed beyond the scope of a function that's being like a private variable basically. You can collapse all these names to something that means the same thing. Anyway, so the most important reference is by this man, James Kyle, who's gonna be at the conference, right? Babel plug-in handbook, fantastic resource. Also, there's a Babel handbook but this part especially I love. It is a very nice guide. You know, you read this for an hour or two and you know how to make plugins at a basic level. It's very nice. Definitely check it out. So a little bit about what I've been working on. Oops, one second. So I've built a couple of interesting plugins, I think. One is it sort of resolves the paths of modules that you're importing. So if you're importing say the named module from your node modules folder, it'll trace exactly where it's located relative to the source file and replace that, substitute the path, okay? Again, like on its own it means nothing but you combine it with some other stuff. For example, this one I'm also using to turn var foo, you know, require common JS style. I'm turning that into ES 2015 modules, right? So you see where this is going. I'm kind of transpiling modules from common JS and mapping them to relative paths to each other rather than name dependencies. And I've kind of combined these and a couple of other plugins into a tool which I can now use to take the stuff that you would do with Webpack or Browserify to bundle things. I can now transpile all of my files, including my node modules folders and turn them into individual JavaScript files that I can serve up on a web server. That's using, for example, HTTP2. If you were here at a previous talk that I gave, I'm a very big fan of HTTP2 server push. So I can serve up rather than rather, instead of a one big bundled file, I can serve up 300 small files and get the benefits of caching and things like that. So combining a couple of battle plugins, let me build that relatively easy over a couple of weeks of my free time. And I thought that was kind of interesting. So I might talk more about this at another time. Probably a JS Conf a little bit. Probably all of it. Okay, so I'm Sebastian and that was my talk. Thank you. Is there any time for questions? No. We have a little bit of time for questions. If anyone has a question. Is anybody using Babel for other languages than the others here? React, JSX, Flow, there's lots of extensions to languages, a flexible concept, but I think fundamentally it's not set up to really become like an HTML transpiler or a CSS transpiler or something like that. Like there's still some parts within like Babylon that would make it really hard to do that, I think. But maybe somebody pushes it in that direction. I don't know. It'd be interesting. Okay. All right, thanks again. So we're not here handy. We're talking about placement.