Episode 75: Building A Snake Game in LWC with Aditya Naag Topalli

 

 

Aditya Naag Topalli is a Lead Developer Advocate here at Salesforce. He started out building web pages and applications but didn’t stop there. Those beginnings led Aditya to amazing things such as building a snake game with lightning web components. Today we broke down why and how Aditya built the game and the lessons learned along the way about things like performance and controlling the DOM.

Throughout the show, we also discuss what Aditya’s role as a developer advocate looks like and talk through everything LWC.

 

Show Highlights:

  • Why Aditya shows himself building code from scratch in his demos.
  • Why he wanted to build a snake game in LWC.
  • Why not being in charge of manipulating the DOM is a best practice for lightning web components.
  • How to control the flow when it comes to rendered callbacks.
  • The performance benefits of using LWC instead of classic.
  • How to decide which data to present to a client.

 

Links:

 

Episode Transcript

Aditya Topalli:
And that fascination still was there with me, obviously, my course was computer science. And at that time I particularly hated looking at websites that didn’t look good.

Josh Birk:
That is Aditya, a lead developer advocate here at Salesforce. I’m Josh Birk, your host of the Salesforce developer podcast. And here on the podcast, you’ll hear stories and insights from developers, for developers. There Aditya is talking about his early experiences, building out web pages and web applications, which led to his experiences that we’re going to talk about today, which includes building a snake game with lightning web components. But we started about how his previous role is similar to his current one as a developer advocate.

Aditya Topalli:
I was actually a part of the pre-sales team, also in my previous company. And that also involves building demos, which I seem to like better than building solutions based on customer’s requirements. So this is a full-time opportunity where, explore something new, build demos on that, and inspire developers. Yeah, you don’t have the pressure of deadlines, at least. For most of the time, of course, Dreamforce and all is different.

Josh Birk:
Every now and then. Every now and then, yeah.

Aditya Topalli:
But then yeah, you’ll get to work at your own pace. So that gives a lot of room for us to think creatively. So that is what I love in this role. And that is not [inaudible 00:01:32] hanging on your head.

Josh Birk:
Yeah, I agree, there’s definitely some advantages to working for a client that’s totally fictional. So yeah, I hear you there. Well okay, well let’s talk about some of that stuff that you’ve been doing. You’ve got this video doing wonderfully on YouTube, and I want to talk about the content, but I also want to talk about the style, because it’s come up before in my conversations with Kevin and with [Mo 00:01:55]. And you’re building a solution slowly, mistakes and all, going back, fixing your work, et cetera. What’s the advantage of that style of video, as opposed to say, a really polished video where you’re only showing completed code that you know where everything works?

Aditya Topalli:
So in my personal opinion, I think for developers who are watching the video, doing it from scratch is more relatable. If you show a fancy demo and you say, “Yeah, all of this is the code behind it,” and you just highlight one or two lines, they know that, “Okay, this is possible.” But then when you build it from scratch, you actually show how you as a developer think through the solution. So it’s not just about writing that piece of code. You also talk them through the process of, “Okay, so now here is a requirement and here is my thought process on how I want to build it.” So innovate to the developers watching the session, they don’t just learn how to write that piece of code, but they also learn how to think of a solution for that problem.

Josh Birk:
Yeah. One of the things love about it is that you actually go to Google to cut and paste code that you know, and you actually quip in the video at one point that you’re doing it simply because it’s faster and it’s easier to pull it straight from the documentation and then just put it into your code.

Aditya Topalli:
Yeah. That’s true with almost all the developers. I am really using the word almost because I want to be inclusive, but I think it’s just all the developers.

Josh Birk:
Yes.

Aditya Topalli:
And yeah, why do I need to remember something if I can just copy paste it from Google?

Josh Birk:
Yeah. It could be turned into an ongoing joke on the pod that that stack exchange is one of my favorite ideas, so I completely feel you there.

Aditya Topalli:
Yeah. And the advantage for me at least clearly is spelling mistakes. So I don’t forget a letter and writing something and bang my head over, “Oh, what’s the mistake? It looks almost exactly identical.”

Josh Birk:
Right. Okay. So specifically the first video we’re talking about, it’s about building a snake game in LWC, which brings me to my first question on that, why build a snake game in LWC?

Aditya Topalli:
Okay. So that’s actually an interesting question. So even I, I did not start off by thinking, “Okay, let me develop a game on Lightning Web Components. It just struck me. So during this whole lockdown, when everyone [inaudible 00:04:23] was sitting at home, I don’t know about the US but at least in India, Ludo King as a game became very popular.

Josh Birk:
Really?

Aditya Topalli:
Yeah. So almost anyone you see is playing Ludo and it’s quite addictive. And one of my friends who also works in the ecosystem, he said, “Okay, let me try building Ludo on Salesforce.” I thought, “Yeah, that’s a cool idea.” And then it struck me, “Okay, building Ludo looks a little bit complicated with all of the different pieces falling together, you will have to put a dice in between and all of that.” So I just Googled, “How do you build games using JavaScript?”

Josh Birk:
Oh.

Aditya Topalli:
And that is when I saw snagged game being a very popular video out there in the JavaScript world. So I thought, “Yeah, let’s do that using Lightning Web components.” And one problem off the bat I faced was that most of the videos only talked about building games using HTML five canvas.

Josh Birk:
Oh, right.

Aditya Topalli:
Yeah. It’s easy. You just draw a canvas and everything else you do is a Canvas function.

Josh Birk:
Yeah.

Aditya Topalli:
I thought, “No, that’s not going to add any value to LWC.”

Josh Birk:
Right.

Aditya Topalli:
So I had to dig further in the internet to look at some code samples on how people did it with pure JavaScript and not using Canvas.

Josh Birk:
Got it.

Aditya Topalli:
And that is when I started building it using Lightning Web Components. And then what I realized is there are some decisions that I took when building the whole grid. If you watch the video and there is a grid that I built. And the way I rendered the grid, I did it in one way, and then when I was looking at the output, it turned out it was not performing enough. So there was a lag in the game. So then I had to do [inaudible 00:06:16] some parts of the code, which is when I realized, “Okay, this is something interesting. And it’s also fun, so let me do it as a Trailhead live session.” So that’s how the session came about to be.

Josh Birk:
Okay. Now, early on you state very directly that you yourself don’t want to be in charge of manipulating the DON. And why is that good? It feels like it’s actually a best practice for Lightning Web Components, but describe to me why.

Aditya Topalli:
Okay. So in general, when you try to manipulate DOM using JavaScript, it’s slower. And the way Lightning Web components addresses that fact is that it has a binding between the JavaScript code that you write and the HTML file. So we have implemented all these decorators, like track, which is no longer necessary for most use cases. So the framework itself implicitly knows how to render the DOM, and it does it in a more performant way. I think the LWC team has spent a lot of time making sure LWC is performing. And they have already considered all these cases where you update something in the JavaScript file, and then it didn’t reflect something on the DOM. So they know how to do it efficiently. Versus you manually creating a DOM element and then adding its property. So it takes up a lot of time for it to go through all of the DOM elements and then pick a particular element and then render its style. So there’s a lot of repainting that happens in the DOM queries is generally slower. So that is why it is listed as a best practice, so we generally use that.

Josh Birk:
Well, and I appreciate that because I remember my early days of JavaScript was nothing but DOM handling and nothing but DAMA handling through two browsers at the same time, fighting between Netscape and Internet Explorer. And so it’s just nice to see development finally get to a stage where you’re just letting the framework do all the work for you and you get to do all the cool fun stuff. Quick question on the track, because you ended up having to track a variable. So what’s the distinction in modern LWC between variables you need to track versus the ones that you don’t? To put in the track annotation to make sure that the client is going to get updated.

Aditya Topalli:
Yeah. So that’s a tricky concept back then, but I think we relatively simplified the way we message it to developers. So basically when LWC framework launched, to make sure our property was reactive, that means if the property is updated, the UI has to be updated. So to make sure that happens, you had to explicitly put track as a decorator in front of the property. But in about six months or so, we removed that necessity. And the clear distinction here is, as a developer, if you’re listening to this podcast, if you want to remember when to use track and when not to use track, any primitive variables are tracked by default, which means if you declare something like a string or a number, those are primitive data types, debt. All of those are tracked by default.

Aditya Topalli:
But if you have non primitive data types like arrays and maps, those are not tracked by default. And there is actually a distinction in that as well. So when we say tracked, it means whenever there is a variable reassignment that is when the UI gets updated. So let’s take this example, okay, I have a bullion property. So I declare it to be false in the beginning. Now, when I update it to true, it means I’m actually reassigning the value from false to true. So it’s automatically tracked. Now let’s say I have an array, which is a non primitive data type. And this time let’s say the array has two elements, one and two. Now, if I reassign, meaning that if I say A is equal to two comma three, that means I’m reassigning its value so its tracked.

Aditya Topalli:
But what happens if I use any function to push an element to the array? So let’s say A is equal to one two, and then I say, “A dot push, three.” In that case, just the element inside the array changes. The value itself doesn’t change, meaning that it doesn’t get reassigned. So that is the case when you need to explicitly put the track decorator to make sure the framework knows it doesn’t just track the reassignment, but it also has to track any changes to the elements inside the array or map or whatever you create, which is a non-primitive data table. So that’s the basic difference. So if you’re reassigning, you’re good to go, but if you’re pushing elements, then you’ll have to use track.

Josh Birk:
Got it. And then an early pitfall that you run into, you’re leveraging rendered callback, because you’re trying to constantly have your grid updated, but within the callback, you’re also updating track values, causing the Lightning Web Component to render, which is then triggering rendered callback. What are some of the tricks that you can use in order to control that flow so that rendered callback is only being utilized when you want it to?

Aditya Topalli:
So that’s a trick most developers who have been working on the Salesforce platform are already familiar with. If you think about triggers, and there is a called recursive triggers. How do you prevent recursion and triggers? You will do it using a static variable. So you declare it to be of some bullion value, true or false. And then in the entire execution context, depending on what you want, you set it to true. And basically you put all of your logic inside an if condition that says, “Only if this value is true then do this. If not, don’t do it.”

Josh Birk:
Got it.

Aditya Topalli:
So that static variable is used as a recursive control element. And that’s the same concept we use in the rendered callback life cycle also. So we declare a property on the class level and we set it to true or false depending on our use case. And then we just use toggle its value to determine whether a particular code and rendered callback has to run or not. So same concept, but different execution.

Josh Birk:
Yeah. Well, and talking about same concept different execution, and going back to the “why” question a little bit, when I look at the overall architecture of what you’re putting together, you’re setting up arrays, you’re controlling arrays, you’re feeding that into the callback loop, that data’s getting mirrored into the user interface through the track variables. How different does that sound to other components that you’ve actually built?

Aditya Topalli:
Other components don’t use as much reactivity, meaning that, so the game is a continuously ongoing loop. So the other elements don’t use as much of that concept of a continuous loop, but then the concept of changing something in the backend like an array and reflecting that on the front end is not new. So that is its use case where let’s say you want to, for the lack of a better example, add new filter values. So let’s say you have a text box and then there is a button called “add more”. You click that add more button, and then a new text box pops up.

Aditya Topalli:
And then there is this ability that you can remove a text box. So that’s a use case that is already prevalent, I’ve seen a lot of projects implement such a use case. So in that, what typically people tend to do is, let’s say at the moment I click on the add more button and I have to add a new input element. The general go-to tendency is call a JavaScript method that inserts a new element to the DOM. And as we already established that manipulating DOM that way is slower, and it’s a lot more cumbersome. Meaning that if you add more, there are new elements that get added, and then the page gets slower, you’ll have to manually verify the indexes. And let’s say you want to get the property value of a particular text box in this whole sequence, you’re going to iterate through all of them, a lot of headaches come into picture.

Josh Birk:
Right.

Aditya Topalli:
So instead of that, what you can actually do is define an array in the backend and treat each of these text boxes as new array elements. So you essentially create an array of objects. So whenever you click on “add more”, all you need to do is just add a new object to your array in JavaScript, and LWC takes care of rendering a new text box on the front end. So that way it’s more efficient. And in your JavaScript, to get the value, you don’t need to query DOM elements again, you have the value in JavaScript already. So that’s much faster in terms of performance. And in terms of a developer experience, I think it’s much more easier than you having to query DOM elements. Because one problem that I almost always see when querying DOM elements is that I end up querying the wrong class, maybe I don’t get that element also, then I’ll have to figure out, “Oh, why this element is not being accessible?” So all of that problems go away.

Josh Birk:
It does, nice. Well, in talking a little bit more about performance, one of the things that you did was you had two templates on the client and both of them looking for the conditional of where the snake was effectively, and you reduced that down to one where that one template was just looking for more dynamic variables to know how to render its CSS class, for instance. How important is it change like that? How much paid off do you actually see?

Aditya Topalli:
I think it’s just a matter of personal preference and how you structure your code to be. There are advantages to both. Again, it comes down to, like I said, personal preference. If you want to split it into a different component in the future, so let’s say, I think you’re talking about the game over screen, that’s rendered differently. There are two ways of looking at it. I wanted the output to be an overlay on top of my existing DOM element, which is why I made that change. If let’s say I had a use case where I didn’t need that overlay, I just needed to remove everything and just show a message saying game over, then I would have implemented it differently. So it comes down to that. There is no real pay off between doing it either way, is what I would say.

Josh Birk:
Well, and I think it’s interesting that you’ve provided yourself with a use case where since it’s iterating so quickly, that small changes like this are probably more noticeable. Because your UI is reacting, I think it was over 300 milliseconds, was your timeout. So any improvement you’re doing to LWC is instantly noticeable. And to me, that’s actually, it’s an interesting use test for somebody who, if you’re trying to see your performance, that’s one way you can see it in real time.

Aditya Topalli:
Yeah, that’s exactly true. Even frankly speaking, I was pleasantly surprised looking at it. So the way I implemented it, I thought it would work well. But what happened is, so let’s say the snake was moving from left to right. Okay? And then once it crosses the boundary, I made it appear back on the left. So that seemed to work seamlessly because all of those DOM elements were one after the other in a sequence. But then when it was moving from the top to bottom and it tried to cross the boundary at the bottom and come to the top, that is when I noticed a significant lag.

Aditya Topalli:
So then I was looking at the DOM structure and realized, “Okay, it’s trying to get, not the next sequence element, but to some other element, but as in somewhere else in the whole structure.” Which is when I was like, “Okay, so now that I’m doing the re-render this rapidly, that is why there is a performance degradation.” Ideally most of your production use cases, the components are not going to be this complex. So you wouldn’t really notice it and understand how small tweaks can make the performance so much better.

Josh Birk:
Okay. So now you’ve got another video talking more broadly about performance on Lightning. First, maybe a thorny question, but if somebody is still on classic because they think that’s more performant, what would you say to them?

Aditya Topalli:
I would say no comments, because one thing definitely is that Lightning Experience in terms of user experience. So if your customer is using Lightning Experience in production mode, it’s definitely much faster. And of course, you know lightning experience is not just a page that shows you information from your database. It’s much more interactive than that. So there are a lot more elements that Lightning Experience adds on top of classic. So from a customer standpoint, yes, Lightning Experience is all the way to go if you’re still on classic, [inaudible 00:19:44]. But then when it comes to developer experience, that is a mixed bag.

Aditya Topalli:
So I have already seen, practically when I was working on that webinar, that let’s say I wanted to go to the system administrator profile, let’s say. To do that in Lightning Experience, because when I’m developing in [inaudible 00:20:06], I enable the development [inaudible 00:20:07]. And then the framework is not minified and there’s a lot going on. So let’s say I want to get two profiles. It definitely takes a little bit longer than what it would do in classic. So in classic, I instantly see the profile page, but here the framework loads, the set up loads, and then the profile loads, I’m guessing as an I-frame inside it. So I get what developers are trying to say, but because developers are spending a lot of time in set up, and set up as really not as performant as the end user Lightning Experience, I totally get why developers say Lightning Experience is slower. But then, like I mentioned before, users using Salesforce don’t spend a lot of time in setup. They just look at records, they go to tabs. And once the framework has loaded, all of it is pretty quick.

Josh Birk:
Yeah.

Aditya Topalli:
So that is what is my take on it, to be very transparent. So my session on performance was really focused on how better you can even more improve that end user experience.

Josh Birk:
Yep.

Aditya Topalli:
As a developer, there is nothing much that we can do about it. Hoping that we will still come up with a lot more enhancements. Object manager is the best enhancement I’ve seen. So instead of me navigating to objects and clicking on a particular object in classic, that works, but object manager is much more functional. I get to filter through them easily. And I think object manager has moved away from that classic experience in an I-frame, which is why it is much faster. So I’m thinking as in when we move set up from those classic I-frame experiences to Lightning Experience, developers will notice that improvement.

Josh Birk:
Yeah. And I think it’s also good to point out for that end user experience, if I go back to my interviews with [Chris Gray 00:22:02] and [Kevin Hill 00:22:03], and they’re talking about how the future of not just Lightning Web Components, but web components in general, is the browsers really being able to handle the heavy lifting of the tricks with the shadow DOM and all of the stuff that the framework’s goal is to basically be rendered obsolete. And that’s a future of really high-performance webpage that classic will never see, because it does not have a path to that standards-based web framework where some future iteration of Internet Explorer is going to be crazy fast.

Josh Birk:
And I think there’s lessons from the past that can work today. So for instance, I used to talk about visual force and I can quote a visual force engineer here who used to always tell people, “Don’t take your data truck up to the data dump.” Don’t pull all the data down because it’s going to increase the size of the view state, which increases the size of the client to server track. But we don’t have a view state in Lightning Web Components. But how true do you think that still is that you should be trimming the fat in the terms of the data that you’re trying to represent to the client?

Aditya Topalli:
Yeah. I think the answer is twofold. First thing is, can the user consume all of the data that you’re showing to them?

Josh Birk:
Yes, good point.

Aditya Topalli:
So if you are able to, let’s say, I think in the web terminology, it is called above the fold and below the fold.

Josh Birk:
Mm-hmm (affirmative).

Aditya Topalli:
So when a page loads, what is it that the user has to see? What is important to them? Only if they really need something will they scroll or click something else. So what is the point of getting all that data, which any of us are not going to show on the screen above the fold? So that’s first point of it on why you need to lessen how much data you get. And the second one of course is your bandwidth. Take WhatsApp as an example.

Josh Birk:
Okay.

Aditya Topalli:
Maybe you have an iPhone that takes a picture, which is 10 MB. But when you compress and send it over to your friends, it doesn’t send the high quality image, it lowers the quality so then it is much more faster, because not everyone is always on wifi. On mobile data also you need to be able to get that same experience. So if you would download all of the data, let’s say all the photos, everything in high quality, you might end up using 10 MB of data. And if my internet is slow, I keep looking at that page for half an hour. And that’s not really an experience that you want customers to have.

Josh Birk:
Right.

Aditya Topalli:
And I actually speak about this from a very practical experience. So from my previous company, there was a client where they don’t always sit in front of a system. They’re a property based company, so they go out on the field, they go to that apartment, and they do something on CRM for that. They inspect and they take down notes. They use Salesforce for a lot of things onsite. And onsite, they might not always have good coverage of internet. So how do you make sure those people are able to better work with Salesforce? Of course, offline is one way to go, but then your Lightning Experience, if let’s say they don’t want offline, they want it always to be live, but still be as performant. That is when data comes into picture. That is one classic shift from, pun intended, classic to lightning. Is that, like you already mentioned, visual force [inaudible 00:25:35] render on the server, and then it comes to the client. So your whole HTML dump along with your data comes at once. But with Lightning Experience, it’s all browser.

Aditya Topalli:
JavaScript loads your framework, it does most of the heavy lifting, and you only need to go to the server for data. If the framework and the browser is taking so much of load, why do you want to get all of the data and increase its load? So that is what is important. And the second or third, I think, most important thing is your memory on the system. You can clearly see a performance degradation if you’re, let’s say rendering 10,000 rows of data or CSV on your browser. Because your data is coming in, which is good, but then you’re doing something to render it on the browser. And each browser render, let’s say you have a text that you’re getting, you’re creating an HTML element for it. So the more number of HTML elements that you keep adding to your browser, the more performance hit it is going to take. Unless you have a 64 gig Ram, you are going to notice degradation when the number of DOM elements on your browser increases.

Josh Birk:
Yeah.

Aditya Topalli:
So there are so many nitty-gritties to why you should not get a lot of data. It’s not just always data size, but it can also be rendering problems.

Josh Birk:
Yeah. Well, and you do a great job in the video of highlighting specifically where in the transactions you have control and you don’t have control. Obviously we will be linking to that in the show notes because it’s great stuff, and we only have a half hour to talk about an hour’s worth of webinar, kind of thing.

Aditya Topalli:
Small correction there, it is an [inaudible 00:27:21] webinar, it is one of my longest webinars ever, it’s one hour or 40 minutes. I think movies are smaller than that.

Josh Birk:
I love it. I love it. Okay, so let’s quickly shift topics. Just to give it a shout out, the India crew has been working on a new series called dev talkies. Tell me more about dev talkies.

Aditya Topalli:
Okay. So these ideas stem from lockdown. If you’re sitting in your home, you get all of these ideas. But seriously speaking, six months into the whole lockdown, even we started getting mixed up with all of the technical content out there. So every day I see there is some other technical session, and it’s an overdose of so much technical talk.

Josh Birk:
Yeah.

Aditya Topalli:
So we had this idea back then where we do something fun while still keeping it relevant for developers. And that is where this whole idea of dev talkies came in. But then it took this time to materialize and we were finally able to do it in January. But the core intention behind doing dev talkies is doing something that is not purely technical.

Josh Birk:
Okay.

Aditya Topalli:
So you’re looking at a talk show, you’re getting to know about people. And at the same time, there are one or two technical aspects to it that you intrinsically learn from that session. So we have sprinkled technical topics all over the talk show innovative that that is an interview that [Karen 00:28:55] does with one of our guests.

Josh Birk:
Got it.

Aditya Topalli:
Immediately, we follow it up with two or three minutes quick tip on how you can do something. So you’re looking at the interview, you’re inspired, you’re in that zone, and then suddenly our technical tip drops, so then you’ll pay attention to that. And the fun element really comes in during the game show, which I’m hosting.

Josh Birk:
Nice.

Aditya Topalli:
So in the game show, we big popular games and we’ve added Salesforce flavor to it.

Josh Birk:
Okay.

Aditya Topalli:
So it’s still fun, but you learn also in the process. So we are trying to incorporate that learning everywhere, but it doesn’t seem like you’re sitting in a session and taking in all the knowledge. You’re looking at, let’s say, somebody else play the game. And then if they make a mistake, I think that’s how you remember stuff better. If you see somebody making a mistake and then there is an explanation given to why that is wrong, that’s when you retain it a lot. And I think that’s helping, people are loving the game show.

Josh Birk:
Nice.

Aditya Topalli:
But yeah, that’s the primary motivation behind doing a talk show amidst of all of the overdose of technical content.

Josh Birk:
And that’s our show. Now in the show notes, we will have links to both of Aditya’s presentations. So if you want to book a little time to watch those yourselves, there’s a lot of great detail in them. Now, before we go, I did ask after, his favorite non-technical hobby.

Aditya Topalli:
My favorite non-technical hobby, recently, I picked up painting.

Josh Birk:
Oh, nice.

Aditya Topalli:
So I bought a lot of canvases, which I’m yet the paint. So yeah, I’ve picked up that as a hobby and I’m planning to decorate my home with all of my paintings.

Josh Birk:
Nice.

Aditya Topalli:
And hopefully a hundred years down the line, they’ll have some value.

Josh Birk:
[crosstalk 00:30:48]. Any particular style of painting?

Aditya Topalli:
I’m not yet that mature. Hopefully they’ll name that style after me.

Josh Birk:
Nice. I want to thank Aditya for the great conversation and information, and as always, I want to thank you for listening. Now, if you want to learn more about the show, head on over to developer.salesforce.com/podcast, where you can hear old episodes, see the show notes, send links to your favorite podcast service. Thanks again, and I’ll talk to you next week.