 everyone. Am I audible to everyone? Perfect. Everyone's back from lunch. I hope you guys are not sleepy as such, but even if you are, you'll just avoid some of the mistakes that I might just make. But it's very happy to see such a huge number coming up for the conference. Everyone, including the speakers, organizers are, everyone is really happy to see you all in this huge numbers coming up here. And I'm really honored to be speaking for react to slightly up. Okay, perfect. All right. So the topic that I'm going to talk about is, is a very fancy background and a very fancy topic as it looks like the magical land of ASTs and with Babel ESLint and code mods. The purpose of this name was when I when I initially started coding in react or let's say any framework or JavaScript as such, Babel ESLint and these things looked really magical to me. Things were getting auto corrected. Prettier was auto indenting my code and really I didn't have to do much here because this was all magically happening behind the scene. Async await was working even though it wasn't supported in some browsers. Internet Explorer was working well with even Async await and promises. So these things were all happening behind the scene with me being completely unaware of how Babel is doing all of these. So that was really magical for me how these things were happening and the purpose of this talk here is to reveal that it's not that magical and ASTs as the name suggests sounds really complicated at the beginning that you need to understand how machines work or how bits and bytes work. It's not as complicated as it looks like and hopefully once the stock is over once entire conference is over when you go out of this room you will all understand how to create Babel plugins understand how to create ESLint plugins and be better in writing your code writing better optimizations writing better organization white linting rules and you probably will no longer require to do a find and replace into your entire application or something changes. You would probably use a code mod to do a large scale refactor on your code base. So that's what the purpose of this talk that it will open a new wide spectrum of possibilities for you you can obviously do a lot of open source contributions if you learn how to how to write Babel plugins you can write ESLint plugins for your organization. So a lot of opportunities that will become available if I'm able to convey the message of this talk and be able to help you understand how easy it is to create these plugins. So how many of you here have actually have actually created Babel plugins or have worked on any sort of AST parsers or ESLint plugins? Is there anyone who's created one? Oh, so there's one I can see and okay, two here. Perfect. So three other, right? Perfect. So then for the rest of you, I think there's going to be really interesting session and I hope you learn something out of it. And that's what the objective is. I'll quickly go through the introduction part. My name is Vivek Nayar and I work for a company called a Strusting Social. We are a fintech organization working for doing credit scoring and producing products. And if after the talk there are any other questions which are unanswered, we have a BOF session as well, which is specifically targeted to Babel plugins ESLint and code mods. But even then, if there are certain questions which are not able to ask here or in BOF, that's the Twitter handle where you can ping me and it will be I'll be happy to chat on any plugins that you create. I'll be happy to contribute to them. And there are certain plugins that I have created, then you can obviously do your open source contributions to them. So that's the Twitter handle you can follow me and if there are any questions that are unanswered, that's the place to find me. So an interesting question that immediately comes up is I've been talking a lot about ASTs. I've been talking that everything with Babel ESLint and code mods revolve around something called as an AST. But what is an AST? How do you explain it to anyone in very layman terms? What is an AST? So abstract syntax tree, a very simple thing. But if you see here, I've written a very simple code snippet, which says const a equal to three and a plus five. So the very first line says it's a variable declaration that I'm doing. And then I'm assigning it to a value which is a numeric value, which is three over here. And then in the next operation, what I'm doing is I'm doing an addition operation. So it's a plus five. So the very simple thing that I'm writing in my VS code or any editor, there's an assignment and then there's an addition that's happening. But this is what you write, you and me write in our editors. But this is what the computer gets to see. So if you see this is a JSON representation of what an AST tree might look like. So some of the keys have been removed to help you better understand what are the important points in it. But the main thing to focus here is the type declarations that you see. So every plugin that you create with ASTs have certain AST nodes, AST types associated with them. So in our example, we had const a equal to five. So that was a variable declaration, which is why you see the very first type variable declaration. So that is the first AST node that we created. Now variable declarations can be many, it can be const a comma B comma C. So which is why this const is a variable declaration. And then you have a key called as declarations, which is an array of variables that you have declared. And all those have a type called as variable declarator. So these types are associated with everything that you write in your code, be it a variable declarator, be it an assignment expression, or you write a sink await, which is an await expression. They all have certain types associated with them. So here we see we're declared a variable called as a. So there's an ID with the name A here. And then we had assigned it to a value, which is five, which is a number. That is why it has a type called as numeric literal. It could have been a string. In that case, the type would have been a string literal. And then finally, our variable had a type called as constant. So that is why the kind is const here, it could be let or where. So this is a very simple representation of what the computer gets to see when it parses your code into an AST. And this is this is a floor flow chart of how things work. Every Babel plugin every when you write a Babel plugin using Babel on as the parser, it always starts with a root node, which is program. In our example, we had a variable declaration. So you see a blue box with variable declaration written in it. Then we had two declarations, which was a assigning it to a value called as three. So you see two nodes on the left side of the tree. One is an identifier, a and the other was a numeric literal three. And then we did an addition operation, which is an expression statement. And because it's two things involved in that operation, a plus three or a plus five, it's a binary operation, which has a left side to it and a right side. The left side was an identifier a and the right side was a value, which is a numeric literal five. And then there's an operator, which is plus. So this is how your AST tree actually looks like when you in terms of the flow diagram. This is how it looks like when you when your code is actually parsed. And whenever you're creating Babel plugins, if at all you can do this diagram on your on your paper, it will better, it will help you better understand writing Babel plugins. So beat beat Babel plugin, beat ES lint or beat code mod or beat any Java compiler or a Scala compiler or anything. They all these compilers follow three important steps. One being take the code, which you and me understand and parse it into an AST, which is an abstract syntax tree. Then you want to do certain transformations to it. For example, I want maybe want to remove certain notes from it. Let's say I've written a code which has debuggers in it, and I do not want those debugger statements to make it to production. So this is the step where and I'll remove those debugger statements. So you can either add, edit, delete your nodes of one AST and transform it into another AST. So this is a second step of any compiler. And the third step is finally you have transformed one AST to another AST. Now it's important for you to convert it to back to a code which you and me understand. So the final step is to generate the code from the new AST that is generated. So three important steps, parse, transform and generate. You write Java, you write Scala, you write whatever language you have. These stages remain the same. So the same thing to, to better understand things. You write a code like this. You parse it. There's a tree that's created. You see three blocks over there. One is a green node. The other is a blue. Then is a red node. I do a transformation on it and I'm swapping the red and the blue notes. So this is a new tree that got created. And finally with generate step, my code is getting generated with the new AST tree. So this is basically I'm repeating these three steps because this is the building block of any plugin that we're going to create today. Pars, transform and generate. And precisely the talk would focus on the basics of AST. It is going to talk about how do you create Babel plugins. It is going to talk about why ESLint and why not other linters which are available. And we'll be doing a lot of live coding. I'll be coding few Babel plugins, few ESLint plugins and at the end code a production ready code mod for react applications. So that is how the talk is structured. What we're not going to focus about is we're not going to go deep dive into how lexical scoping works or how tokenizing works. That is the topic of discussion for some other talk. So some of the production ready plugins which I use in my applications and probably some of you might also be using. One of them is Babel plugin, Lodash. Majority of the time when we see our final bundle that gets generated, it's usually bloated because it's either moment JS which is taking a lot of time or it's either Lodash which is occupied a lot of space for us. And it usually happens because you're importing the end because you're importing entire Lodash library or you're importing entire underscore. So this plugin helps you with that. This plugin will only import what you're using in your particular code and will not bloat your production bundle. So this is a production ready Babel plugin with someone has created with the understanding of ASTs. Another important plugin which has been used is Babel plugin transform react remove prop types. Prop types people working with react would understand that it is something that we use for while we are developing our application to make sure that we see if you're passing a prop of a different type to a particular react component and we throw a warning or an error to us. But you do not want your prop types to make to production bundle. So this particular plugin will remove those prop types when you're generating a production bundle. Another plugin that's very useful is react class to function. We have been talking a lot about hooks these days and people are running behind converting all their class components into hooks. But this plugin had been already there long back. What it basically does is you have a class component. You give it to this plugin and this plugin would convert it into a functional component. This is a plugin that I was recently working on which is better async await. This is inspired from Golang because that's what I'm recently started learning. So usually when you write your async await syntax, this is how you write. You put them in a try catch block API dot get data. If there's any error in this API calling logic, the catch block will call it and you call handle error. But if you have multiple of these API is in your function, you either put one try catch or you have multiple try catches, which is eight increases the lines of code and probably is difficult to read as well. So this plugin was inspired from how Golang does it. So you see there's an API dot get data on the left side. There's an array expression whose 0th index is an error and the first index is a response. So you just check if error is populated, then something went wrong in the API. And if response is populated, then you got the response and it was a successful 200. Okay. So you don't have to do anything. This plugin basically make sure that when you make an await call to an API error or response, either or fit will be populated. So you don't have to put try catches now because that plugin had already put it in the code that it has written. So we'll we'll quickly do a demo of few Babel plugins to help you better understand how all these things work. This is all theoretical at the moment, but these plugins will help you understand. So one important thing when you're developing any Babel plugin or ESLint or working with AST, this is the most important site that you have to be on. It's AST Explorer and the advantage of the site is that it will tell you the AST representation of what your code will look like. You can transform it here. So majority of your time you will be spending writing your code on this particular AST Explorer and then taking it to NPM or publishing it somewhere. But first you do your experiments on this particular web page. So what we are going to do is a very simple plugin to start with. Let's say is it clear to everyone? Is it now? Perfect. One more. So one thing to notice here is you can choose different parsers for your AST tree. There's acorn, which was initially available, which is Babel ESLint for your ES Linting. You have Babel on 6, Babel on 7, Esprit is the parser which ESLint uses by default. Babel on is the one which we are concerned about because we are writing Babel plugins at the moment. So I'll go to Babel on and select this parser. And what this very simple Babel plugin is going to do is in your code you might have a syntax like this. You write const A equal to five and then you might have a debugger statement somewhere and then you do A equal to A plus six. Now there are a lot of companies and there are a lot of organizations where there are no proper PR reviews in progress. There is no pipeline wherein people could figure out that there's a debugger statement, which is making it into the master branch or going to production. So in all those scenarios, you can write a Babel plugin, which will make sure that if there is debugger statement anywhere in your code, this Babel plugin will remove it. So how will we do that? The advantage is first for this AST Explorer, you click somewhere on debugger. Let's say I click on debugger here, it gets highlighted on the right hand side and let's me know which AST node I have to target. So it says I have to target a type called as debugger statement. So I go to VS code. This is the bare minimum of how a Babel plugin should look like. It exports an object. It returns an object which has a visitor key in it visitor keys basically because it follows a visitor pattern, which is which is a different topic of discussion. But visitor pattern is an object is a visitor key has an object. And here you basically say what node do you want to target? So I want to target a node called as debugger statement. So when Babel, Babel on will start traversing this dream. When it reaches this particular path, when it reaches a debugger statement, I want this baby plugin to remove wherever there's a debugger statement. So I say when you reach this path, remove this debugger statement. So a very simple example, there are complicated plugins also, which we'll do, but this is a very bare minimum of how you can remove debugger statements. So you say part or remove and anywhere there are debugger statements in your code, this will remove it. So let's test it. Let's add this Babel plugin to our plugins area here. So we say my plugin lies inside plugins directory slash remove debugger. And now let's run this. The file that I want to execute it against is remove debugger test. And you see, I have a const a equal to five. There's no debugger statement, which is present over here. There was a debugger statement initially. This is what the code was const a equal to a plus five and a debugger statement with this Babel plugin. It has removed the debugger statement, which was present in that code. And if you run it against your production bundle, everywhere there is a debugger statement, everything will get removed. All the debugger statements will get removed. So this is one simple example of how things, how they will plugins could be written and how you can target different nodes. Another example that we can go is a lot of times it happens. A very simple thing you write const a equal to five. And then for debugging, you have alert statements in your code. Let's say you don't want to put you have alert statements and now against very similar to how debugger statements you do not want alert to go into a production with ready application. So a you do how you did with debugger statement, you remove them or you convert them to something like a sentry reporting or you report it somewhere. Here we are going to convert it into a console dot log statement, which is harmless for us at the moment. So what we want to do is we want to convert this alert statement. So I click on alert and I see that it is something called as a call expression on the right that I see. So what a call expression, any function calls that you do is a call expression. But if you are doing an API dot get data, which is which is an object and a property and then you calling a function that is called as a member expression. So the two important things that we need to understand is what a call expression is and what a member expression is. So any function call is a call expression and any object property then a function call is a member expression. So we understood that we need to target something called as a call expression. So we quickly go to our code and the bare minimum is ready. I say the thing that I want to target is a call expression. So I say, okay, this is what I want to target. And now I have to do something with it. I need to replace it with console dot log. Now, how do you do that? You click here and you figure out that, okay, this call expression has a callee and that callee has a name alert. So I say I want to target call expression whose callee has a name alert. So I go here and say if path dot node dot callee dot name is equal to equal to alert. I want to do something with this. So now what I want to do is I want to replace it with a console dot log. So let's see how that looks like. So this will look like console dot log. So again, I click over here and figure out that a console dot log looks like again, a call expression. But the difference is that the callee here is a member expression, which has an object which is console and a property which is log. So now I understood that I need to replace it with a call expression. So I say path dot replace with replace it with a call expression. Call expressions, callee would be a member expression. Member expression has an object. So I say that's an object, which is an identifier with a name console. And it has a property with an identifier called as log. And this call expression if I see takes a callee in arguments as well. So arguments is A. Now how do you get arguments because in alert statement, you already have arguments. So I take the arguments out of that alert statement, say const arcs is equal to path dot node dot arguments and pass it to this new replacement that I've done. So this is a call expression. If it's an alert, take the arguments which are passed to alerts now replace it with a call expression, which is console dot log because it's a dot operator. So it's a member expression, which is console log. And then you pass the arguments to it. So let's add it to our plugins area. It's inside dot slash plugins slash convert alert to console. The code that I'm trying to convert is this. It's an alert. I am here. I want to convert it into console dot log. I'm here. So I'll go and run this code. This is inside convert alert to console test. And you see alert. I am here. Got converted to console dot log. I am here. So the alert statements everywhere in your code will now get converted into a console dot log statement with this plugin. So far so good. Perfect. Another complex example that we're going to do is most of us write things like this one comma two comma three. You map over it. You get a value and you say value into two. Let's say you want to just multiply it by two. This is an arrow function expression here. And there are scenarios wherein your browser might not support it and you want to convert it into a function expression. So you would want to convert it for any number of reason. Let's say you want you do not want arrow function expression and you want to convert it into something like this. So you want to convert it into something like this. Oh, okay. Yeah. So you want to convert it into something like this. So now we click here. As always, we figure out that the note that you want to target is an arrow function expression. So we go to our code arrow to function. We say the note that I want to target is an arrow function expression. Get me the path of it and we'll do something with it. Now I need to extract this value that you see over here because this is the same thing that needs to pass to this function. So how can I get that? It's inside params as you see on right. So it's arrow function expression and params. So I extract this out from here. I say const params is equal to path dot note dot params. I also want the body to be same because that's exactly what I'm going to do. Except the return statement. Everything is same. So here if I see the body is a binary expression, which has all the things in it. So I copy the body as well. I say the body is path dot note dot body. So get me the body, get me the params and now I will replace it. I'll say part dot replace with. I want to replace it with what? Let's click here and it says I want to replace it with the function expression. So I go here and say I want to replace it with the function expression. Babel types is the place where you can figure out what is needed by home. So what are the parameters needed? I see function expression takes an ID. It takes params. It takes body generator for generator function and async if it's an async await. So I know that function expression here would need an ID, which can be null for now. Params we have already extracted. So I say, okay, just copy paste the params that I've got. Now I can't place the body directly here because the body here looks slightly different because there are parenthesis here and that parenthesis basically means it's a block statement. It's a block of code. So when I click here, I figure out that the body is a block statement. So I say, okay, replace the body with a block statement. That block statement, if you see takes a body, which is a return statement. So I say, okay, I the body will be a return statement and the body would be what I've already extracted about. So this is my plugin. Now let's try to add it to our run.js file, which is our array of Babel plugins. And we say it will be plugins slash what was the name of the file arrow to function arrow to function. Okay, now when I run this file, it should lead to an error. And why I'll tell you test arrow to function. Okay, it leads to an error as expected. It's saying property key expected, but got this thrown you property body expected of type array, but got an object. Your body can have multiple statements in it and it cannot be a single line. It has to be an array of statements. But what I've done in the code that I've written, you see the block statement that I've written, it just has one line in it return statement. Instead, it should be an array. So let's just convert it into an array here. And now let's try to execute this. And you see your arrow function expression is now converted into a function expression with a return statement with everything and you return an arrow function got converted into a function expression and with very few lines of code. So this is what ASTs if you understand ASTs, this is what you can do with them. These are probably a smaller example. So what all could be done, but you see the bigger production level available plugins which have been used, they all follow the same fundamentals, target certain nodes and modify things in them. So those were the plugins that I had for demo for for Babel. Most of the things that you saw, I was adding plugins into a particular array of plugins, your plugins and presets go to a file called as Babel dot a Babel RC file. It's where you specify your presets and your plugins. This is how a very simple Babel RC file looks like. I have react ENV and I'm using a plugin called us transform object rest spread. So now a question that arises that immediately came to my mind is I've understood what plugins are, but what are presets? So Babel presets are array of Babel plugins. So you can either publish one plugin or you bundle them all together as an array of plugins and publish it as a preset. So if you want to look at what Babel preset ENV comprises of this is from my code base, it may vary for you. But this is what Babel preset ENV has. These are the plugins that come bundled with it. You can enable the debug mode in your Babel preset ENV and it will print the plugins that it is using a sync to generator because I does not support us in Kuwait. So that is why this is there. And there are a lot of other plugins as well. So presets basically being an array of plugins and another important question that immediately comes to mind is what is the order of execution? Are plugins executed first or are presets executed first? And how does that happen? So plugins are executed first and top to bottom and presets being an array of plugins are executed in the reverse order from bottom to top. So the order of execution is plugin from top to bottom and presets from bottom to top. So yeah, so that is that is all about how Babel plugins are created. One quick question that comes to my mind immediately after this because it's related to the next topic that we're going to go on. How many of you are actually using linters here to actually have linters in your code? Oh, perfect. Almost all of them, which is which is really great. And are you using ESLint for it or are you using something else? How many on ESLint? Oh, perfect. Then I don't need to explain what other linters were available. Okay. Okay, so this is this is this has happened with most of us, right? You write a code and ESLint tell you that you weren't supposed to do that. And this has happened with me recently because I started working on a code which was in happy and happy node happy's framework for some reason has some weird weird ESLint rules, which is at most of the time, it used to give me an error saying you're not supposed to do that. So I turned off all of them rules and then put mine in it. So this is this is usually what happens with people when we're when we're really started working on a old code base being maintained by someone else. But linters is a very good practice. And why is that because static analysis of code, if you are if you're not really into reason or you're not really got into the TypeScript boat yet, but you still want your production code to be lesser buggy as compared to as compared to what it could be. So have linters in place because that will give you a static analysis of your code that will show you your errors. If you have undefined variables which you're using, if you're trying to import something that does not exist. So static analysis of code, it will encourage best practices. You can have Airbnb style guides or Google style guides to enforce better practices in your code. And finally, if you're using let's say a prettier, which most of us are using at the moment prettier or standard or anything, it will enforce certain style consistency with ESLint. Also, it happens. You can you can say that I do not want allow semicolons or I allow tab versus spaces. So all the styling consistency can also happen with the linter. The other JS linters, which I think none of us are care about at the moment were JS lint, JS Hint and JS CS. JS lint was the very first that came with was created by Douglas Crawford. The some of the cons of it where that it was not there was no configuration file available for it. So you cannot really turn on or off a rule. You cannot put in your own custom parsers or rules to it, which is why it didn't really work out. So JS Hint came into picture, which was a forked version of JS lint. It was it had a configuration file, but it did not allow you to write custom rules. So again, people really didn't like it. And then finally, JS CS came in, which which had configuration files which allow you to turn on and off the rules, but also allowed you to write custom rules. But then it was not catching errors like an undefined variable being used somewhere. So it was not finding potential bugs in your code, but it was telling you if there is a style inconsistency. So JS CS I think recent, not recently, but got merged into ES lint. So finally, yes, lint came into picture, which almost everyone here is working on, which is which is great and using in your applications. You can write your own custom rules. You have custom formatters, custom parsers, a very big example of a custom parser is Babel ES lint. ES lint had its own parser called as Esprit, but then Babel wanted to make sure that all the new features that Babel supports also are shown problematic by ES lint. So they created something called as Babel ES lint as a parser. So that's that's ES lint's parser taken plus Babel's functionalities added to it. And then you have a new parser for linting things, which is Babel ES lint. So very good. You can write your own custom parser. You yourself can write your own custom parsers. You can turn on and off the rules, which are not available for different the linters, which came before ES lint. You can set them to one or error. You can specify whether this will be a warning or an error. This is how an ES lint rule looks on my VS code editor. It will look different on you, but this is this is such a detailed message that it gives you that there's something wrong in your code. An ES lint when you write an ES lint rule, this is this is how a basic structure looks like. You have a meta which says type type is suggestion problem or layout. Suggestion can be this can be problematic, but it will not lead to a buggy code. If you say type problem, then it will be a buggy code. Okay, it will lead to a buggy code. And then when you say fixable code, this basically means when you do an ES lint minus minus fix, this will automatically this rule will automatically fix your code and the create function is the place wherein you actually write your rules. When you're working with ES lint rules, you always create three files. One is your actual rule file. One is your test file and one is a markdown file, which basically is for documentation. So if you have to do. So we choose an Esprit parser. We go and transform as say I want to do an ES lint transform and the code that I want to transform is. I don't want to allow anyone to use promises because async a weight is in place. So I say cons data and I say. Get data dot then. Response and then response. So I don't want to allow anyone to use promises. So I will throw an error if someone uses dot then. I'll tell him or her that you should use async a weight syntax. So I click over here and figure out the thing that I need to target is a member expression and that member expressions. If that member expressions property is then. So I say I want to target a member expression and if that node dot property dot name is equal to equal to then it will help me identify that it's a member. It's it's a promise call. And then I say I will throw an error and how will I throw an error? I will use something called as context. I'll say context dot report and throw an error. The message would be. Use a weight over promises. Promises. This is the node that I want to pass. Okay. So you see it's throwing an error on the right. It's saying use a weight over promises. Okay. Okay. Use a weight over promises, but you see there's a problem here. It's pointing the error and get data instead. It should be pointing the error is that dot then. So a quick fix to that. We say the exact line of code that you want to point an error to. We say node dot property dot LOC and you see now it's exactly pointing to the place where there's an error. So use a sink a weight over promises. This is what that ESLint plugin does a very simple plug in a very simple plug in which you can use in your in your apps at the moment if you do not want to allow promises. The last bit. Yeah. So celebration time it worked. Really I'm running out of time. So so last bit of the talk is about code mods. So when you want to do a very large scale refactor of your code base, this is what you use for writing code mods. We use something called as JS code shift. A JS code shift is a library provided by Facebook, which will help you do a large scale refactor of your code. And how to use JS code shift? You do a global install. You specify what your transformation file is. And then you specify that I want to transform everything that is in the SRC folder. So I say transform everything that's in the SRC folder and it will convert everything. So yeah, so that's it for the talk. These are the certain resources that you can that will help you understand ASTs. There are a lot of them. ESLint documentation is the biggest resource. Then there are certain. So JS code shift has all node level APIs which you can follow to understand what APIs it provides and how to use them. And finally, there's a Babel Handbook, which is like the greatest resource to understand anything about writing a Babel plugin. So yeah, that's it. Thank you, everyone, for listening to it. And if you have any questions around this, then please demo right now. Hi, so you mentioned that JS code shift is for large scale transformation, but like technically does it do something extra to handle those large scale transformations or it's similar? But so if that question is, can I do the same thing with Babel? Is that exactly so? Yes, you can definitely do that with Babel as well. It's just that JS code shift provides you certain certain APIs, which makes it easier for you to do the transformations. So there are certain level of abstractions that JS code shift has provided you for you to easily modify them. And plus there's a recast parser, which will help you do the formatting and pretty printing of it as well. So that is that is also something that comes with it. So but yes, it's very much possible. You can do the same with Babel as well. You can write a Babel plugin and do a transformation. But with JS code shift, what you can do is you can do a dry run of things. So you will understand what the modifications are going to be and whether to commit them or not. And it will give you a proper statistics off to how many files were modified. And then you can actually manually check if there is a correct or not. And then finally merge it to your master.