Video Summary and Transcription
Today's Talk covers various web APIs and their functionalities, including the intersection observer API, screen wake lock API, background sync API, and broadcast channel API. The speaker emphasizes the importance of optimizing performance and using standardized code to reduce application bundle size. They also highlight the need for environmental responsibility in JavaScript development. The Talk addresses handling API support and modifying code to suit different browser implementations.
1. Introduction to Web API
Today we're going to talk about web API and its functionalities provided by our browsers. Before that, let's go over some JavaScript basics. We'll discuss the event loop and how setTimeout works. setTimeout is a web API provided by the runtime environment. Let's explore some lesser-known APIs and dive into the world of web API.
I wish you a warm welcome to today's conference and today's talk. Thank you so much for being here today. Today we're going to talk about something called web API. But before we do that, we need to take a small step back and go to some JavaScript basics.
Can anybody tell me what the output of this code would be? Anybody? Don't be shy. 132. Okay, great. May I ask you how do you know that? Okay, that's correct. That's cool.
So you mentioned there's an event loop, right? But before setTimeout goes to the event loop, we have one intermediate step. Let's visualize this example a bit. We have the first call, right? Which is synchronous. We get that to the call stack and it gets immediately executed. Then we have a second call which is async which needs to go around somewhere and wait for the number of milliseconds that we put. And then it goes to the event loop, right? And then we have a third call which gets, again, executed. Event loop checks if the call stack is empty and then that callback in the setTimeout gets pushed to the call stack and gets executed then. But the question is where? Where does setTimeout wait for that number of milliseconds that we put?
So when we were announcing the conference, some of the speakers were telling that one of the best qualities that we may have as engineers is to be curious. So if you're curious as we are, you would probably go and Google this. And the first link that we might have is this setTimeout from MDN documentation. If we click that, we can see specification about setTimeout function and we can learn all about it. But we can see that it's under the tab called web APIs. If we click that, we can see that actually setTimeout is functionality provided by runtime and not by JavaScript per se, meaning the environment that we execute our JavaScript in is providing us with this functionality. And as we can see, there are a lot of functionalities provided by our browsers. You might recognize most of these, like DOM API or Fetch API or local storage, session storage, service workers. So probably you've used a lot of these APIs. But I was wondering through this list, and I was wondering, what are some of the not so well-known exotic, let's say, APIs that we might use but we are not using in our everyday work? So basically that's what we are trying to explore today. So the answer to this question is web API. setTimeout is a web API. And we've already seen that basically web API is like a huge list of functionalities provided by our browsers. I'm going to quickly introduce myself.
2. Introduction to Intersection Observer API
When I was in high school, I always wanted to study psychology. Now I work as a development lead, teaching people how to deal with stress, communicate with clients, and do technical presentations. Today, I'll share my super powers of web APIs. Let's start with an example using the intersection observer API to determine if an element is visible on a page. We can use this in our real-life projects and presentations.
When I was in high school, I always wanted to study psychology. Now I work my dream job as a development lead, where I teach people how to deal with stress, how to communicate with a client, how to do technical presentations, obviously, and stuff like that. And of course I'm a software engineer at Vega IT. My name is Nikola Mitrovic. These are my super powers of web APIs for you for today.
Okay. We go to our first example for today. Let's say we have a page like this, which is like an empty page and it only has a background. But once we scroll, we start observing something in the bottom left corner. It's a small astronaut, and once that astronaut is fully visible, he says, hello world. We scroll a bit up, and again, the message goes away. We scroll a bit down, and the astronaut says again, hello world. So how did we manage to do this? There is a very cool API called intersection observer API, which basically figures if the element is visible on a page or not.
If we would build a hook in React for this, we would probably call it something like use visible, and it would look something like this. We would pass a reference of an element that we're trying to observe. In our case, it was the astronaut icon. And there are some options, configuration options, that we might provide to the intersection observer. One of those options is root element. So if we pass null, we observe the visibility of an element comparing to the whole document. So we can observe visibility comparing to some other element, like inner element or inner container or something like that. We could put root margin around that. So if we want to catch that intersection a little bit earlier, and there is a certain threshold, so we want 100% of visibility in this case, but we might modify that. We would have a state like is visible, right? And then we instantiate intersection observer. In the callback, we might see that there is an entry object. And on that entry object, there is a property called is intersensing. Once we do that, we can set our state and what's only left to be done is to observe that element. And pretty much that's it. And we return that state. Of course, the example that I showed with astronaut was cute or whatnot. But you're probably wondering how can we use in our real life projects in our real life presentations.
3. Optimizing Performance and Personal Anecdote
We can lazy load images, do infinite scroll lists, and defer animations to optimize performance. Browser support for these web APIs is good, making them safe to use. In our next example, I'll configure my laptop to turn off after one minute of inactivity. Let me take a minute to talk about myself. I love traveling, especially to Italy. The architecture, people, and food are amazing. I enjoy preparing Italian recipes at home. Let's see if my device turns off after a minute of inactivity.
We could lazy load images, so we don't have to load every part of the content on the page initially, and we can do some performance optimization. So once we scroll to a certain section, then we load images for that section.
We could do infinite scroll lists, right? So let's say we have a list of 10 elements, and we put like empty element at the end of that list. We scroll a bit. Once that is visible, we trigger the next request and so go.
We could defer some of the animations so we don't have to run animations, if they're not visible on the page and say, in that sense, we can save some compute power. One of the things that we always should consider when using some of these web APIs is browser support. Here we have the major vendors that are supporting some of these web APIs. And in this case, all of them support this one. So it's safe to use this on the newer versions of each browser, which is pretty cool.
Okay, we move to our next example. But before we do that, I need to do one small configuration on my laptop. Notice that my laptop is not on a battery, but I'm going to put that for one minute. If my laptop has an inactivity period for one minute, it should turn off. Okay, but we're going to see about that.
Okay, you may notice at the very beginning that I didn't talk much about myself. But now I have a minute to spare. So it's my time to shine. I really do like to travel. And when I do, Italy is one of my favorite places in the whole world. The architecture, the people, the food, everything is so amazing. And I don't know what's about this, but so much passion in just one gesture. I don't know. It's so fun to me. Of course, like I said, one of my favorite things about Italy is food. And recently, once I get home, I like to prepare some Italian food recipes. I go to cooking website, and then I prepare food, chopping onions and whatever. And after a minute of inactivity, I didn't time that quite correctly, right? But this happens. Or not. Okay, in this case, my device didn't turn off.
4. Preventing Screen Lock with Screen Wake Lock API
But realistically, what happens to me is that my phone does turn off, and then I have to turn it back on with sticky fingers and whatever. So my device wouldn't turn off, although I had some specific system preferences that it needs to turn off. There is a very cool API called Screen Wake Lock API, which basically prevents our screen from locking. It could fail in certain circumstances, like if your battery level is way too low. We put this in a reference and not in the state because this function will return a value that is held in memory. Use cases include reading an ebook, presenting to the audience, following a cooking recipe, following map navigation, and scanning a QR or a barcode. Browser support varies among vendors.
But realistically, what happens to me is that my phone does turn off, and then I have to turn it back on with sticky fingers and whatever.
Okay, so how did we manage to do this? How did we prevent this behavior? So my device wouldn't turn off, although I had some specific system preferences that it needs to turn off. There is a very cool API called Screen Wake Lock API, which basically prevents our screen from locking. And it can only work if the document is visible, if the user is observing the page at the very second.
If we would do this in React, we would have a hook, let's say, use wake lock hook. But here, the situation is a little bit trickier than in the previous example. We pass that toggle functionality, is it turned off or not? And then if we do that, we call request wake lock sentinel. That function is going to call on a navigator, we have a wake lock object, and we call request method and pass screen parameter. That is a promise. Can anybody tell me why do you think it's a promise? Anybody? Yeah, yes, please. That's a good call. But in this case, no, you don't have to do that to ask permission for this one, but that's a good guess. Do you have maybe any other idea?
Okay, basically, it could fail. That's why it's a promise. And it could fail in certain circumstances, like if your battery level is way too low, you couldn't request the sentinel. And you may notice that we put this in a reference and not in the state. Why is that? Because this function will return a value that is held in memory. And we need to clear that exact value in memory. If we do that in the state, we would lose it. So that's why we have to put it in a ref. And once we clear it out, if we turn the toggle back off, then we would clear the reference, and we would have to call the release method on that reference. We have to do all of these steps. Otherwise, it won't work.
Use cases in this case, let's say we're reading an ebook, we're presenting to the audience, we're following a cooking recipe. We're following map navigation, and we don't want our map to turn off or we're scanning a QR or a barcode. Browser support in this case, well, not as previous. We can see that Chromium vendors are supporting this, Firefox doesn't have support for this. And this blue sign for the Safari means that it's in the experimental phase. So they're getting there, but they're not quite there yet. So that's something that we should be always aware of.
5. Background Sync and Broadcast Channel APIs
Also, in our last example, we have an app called Suemirko.RS that communicates with NASA's API to retrieve a list of habitable planets. We encounter connectivity issues and use the background sync API to perform tasks once we go back online. This API allows us to register multiple tasks in the service worker and improve offline user experience. Another API, the broadcast channel API, enables communication between the service worker and the component.
Also, one of the things in this particular API case is device support. No matter how hard I tried, I couldn't make this work on my iPhone. So that's always something to consider. Okay. And our last example for today, let's say we have an application like this. Called Suemirko.RS. Suemirko roughly translated to English means spaceman, and it's a little bit futuristic app, few thousand years in the future, where we are communicating with NASA's API to retrieve the list of all possible habitable planets, and we want to go on vacation to some of these planets. But in the future, we might also have some connectivity issues, offline issues, because why not. And once I scroll this button, that should trigger a request to NASA's API and retrieve the list of the planets. But as you can see, in the network tab, nothing is happening. Right? Can anybody have an idea why is that? What would you normally expect if we go offline and you try to send a request, what would you expect in the network tab? Yes, you would see that the red request failed. But in this case, it didn't. But what's interesting is that if we go to the application tab, and then we go to the tab called background sync. We see that something is happening there. There is some kind of event registered there, and if we go back online, okay, I just want to show you this. So if we go to that page, we can see the loader. And if we go back online, we can see that there is an event dispatched, and there is a request sent at that very point. After the request has ended, we got a response, we get sync complete at the event. And now we can see the list of all of our possible planets for the vacation, and we can choose the planet to go to. Let's say, TOI561E, sounds amazing. Always wanted to go there. Okay. How did we manage to do this? There is a very cool API called background sync API, which basically provides a way for us to put some task in the background to be done once we go back online. If we would do this in React again, we have our component, like that homepage, and once we hover the button, we call the function to register background sync. On a navigator object, it's part of the service worker actually. We have to register first background sync, and then we can register specific task. The reason why we do this is we might want to have multiple tasks running in the background, right? And in our service worker, we're listening to the sync event, and if the event tag is the same as we registered in our component, then we're going to do something. Use cases, of course, of improving offline UX, or maybe sending an email while we are offline and internet breaks, and we want that to continue. Browser support in this case, again, not so good, but let's wait a bit for it. If you were wondering before how we communicated between our service worker and our component, there is a very cool API called broadcast channel API, which basically allows us communication between the same origins.
6. Bidirectional Communication and Other Cool APIs
We can communicate bidirectionally between the component and the service worker using a specific channel and post messages. This allows us to send and receive data. Use cases include detecting user actions and logging out of multiple tabs. There are other cool APIs to explore, such as the beacon API for one-way requests, the web speech API for analyzing grammar and speech, and the page visibility API for controlling JavaScript and animations. Standardized code is crucial in a rapidly evolving ecosystem with new libraries emerging frequently.
Once we got that tag from the service workers, once we got that event, we triggered the request, we got the data, and we sent that data through a channel to the component, and it goes both ways. We can communicate from a component to the service worker, from a service worker to the component, and so on. We will showcase that now. How do we do that? We connect to the specific channel, and then we call a post message. Through this post message, we can send any information we would like to our component. In our component, we subscribe to that very same channel based on a name, sorry, and we listen to on message event. Once that happens, we will get the data from the service worker. Use cases in this case, maybe we want to detect some user action, log out of all tabs if we have multiple tabs open, and so on. Browser support in this case, we're all cool. Okay, so we can use this safely.
Since we have a limited time today, unfortunately, we have to stop now with the examples, but I hope you are interested enough to research on your own some of the other cool exotic APIs, and if you do, please let me know. I would love to know. But I will give you some bonus points. There is a beacon API if you want to send a request but you don't care about the response. The use case for that is some kind of analytics. There is a web speech API to analyze grammar and speech. There is a page visibility API if you want to let's say stop some JavaScript, stop animations, or if you're watching Udemy and let's say focus mode, you're not observing the page, you want the video to stop, like I'm listening in the background, I'm all observing. No. There is a network API to observe the network conditions. There is a web share API to share some information between devices. Background fetch API if you're downloading a huge file and then you go offline, you want to continue with that download, and of course one of the most exciting and new APIs is probably Web Authen for the Passwordless future. And some of the takeaways. We've seen that some of these APIs do not have browser support. Some of them have experimental support. Some of them might have difficulties with the device support and there is a limited TypeScript support for some of these. But why should we use these APIs? Why is this a good approach? Because it's standardized code. It's standardized code. It's standardized code. I cannot stress enough how important this is these days, especially in our ecosystem where there is a new library coming out every week or every day. So it's really important that we have this one like a single source of truth and we know that it's standardized.
7. APIs and Environmental Responsibility
Most APIs are not hard to learn. We should prioritize using built-in JavaScript features and runtime-provided functionalities. If needed, we can implement custom code or find libraries. This approach can improve performance and reduce application bundle size. With great power comes great responsibility. Let's consider our planet's well-being. JavaScript development consumes a significant amount of electricity. We should be mindful of our carbon footprint. Thank you for attending. Scan the QR code for reference slides. Now, let's address partial API support, specifically WebOuton.
Smooth learning curve. Of course, most of these APIs are not really that hard to learn. And we might increase performance with this. What do we mean with this? Of course, I'm not saying we shouldn't use libraries ever. We shouldn't reinvent the wheel if we already have a library for this. But I'm saying just that if we have something provided by the JavaScript, by our run times, we should go for that. And then if that is not working out for us, then we might implement our custom code or try to find a library for it and so on.
As a total side effect, this might have a performance benefit. Because the bundle size of our applications would be smaller. And that's super important because the next point I'm trying to make, with great power comes great responsibility. So I felt like it's my responsibility to come here and say this. I wanted to talk a bit about our planet. Okay. You're probably wondering what our planet has to do with JavaScript. Well, it does. We write our code, we bundle it, we get that JavaScript bundle that we ship to some cloud platform, right? That cloud platform is basically like a big data center with a bunch of servers which are computers plugged in into electricity. In fact, we use so much electricity that it consumes 21% of the electricity in the whole world. Which is like astonishing to me. Luckily for us, there is a very cool site called website carbon calculator which can provide us information about our carbon footprint. Our planet is our home. We only have one home. And if we don't pay attention to it, if we don't watch for our home, then one day might be too late.
Thank you so much for coming today. This is the QR code, so you might scan it if you want to like slides for the reference. Thank you so much. Maybe personal thing first. We were personal stuff. Like which APIs are you missing? Missing totally or missing like partially? Okay. I'm going to answer the partial support for some of the APIs. That's WebOuton.
Handling API Support and Performance
So the passwordless features should be supported in all browsers. Some of the APIs are not in the GS spec, but they are standardized by W3C and communicated with all browser vendors. Adding multiple intersection observers can lead to memory leaks, but they can be cleared by using a dependency array. Testing for these scenarios depends on the testing framework used. When a browser does not support an API, it can be implemented manually or through available libraries.
So the passwordless features should be supported in all browsers. But for the missing, missing ones, then I would need to think about it. But you can find me later in the call.
Okay. So that's something to move to the discussion room then.
So other question we had is some of these APIs are not in the GS spec. So how can we agree that they are like standards or not? And how should you treat that when you're developing against them? So it's standardized by W3C standard. And it's something that is communicated with all browser vendors. And some of the APIs do not have the support at the moment, but they are agreeing on the API on the interface level that they are going to provide. So it's standardized in that sense. And are there ever conflicts about that? How you should define these standards and how are they resolved? I don't know the specific process, how it goes, but I watched one of the talks from the previous Git Nation conferences, and there is the whole process of how it goes. And I need to re-watch it, but it's a bit tricky, of course, with like any standard, but it's doable. It's possible. Okay. Well, if you want to watch the talk, it's all on the Git Nation website to re-watch.
So the next question we had is, how expensive is it performance-wise to add multiple intersection observers? Will you ever run into trouble if you just keep adding them? Well, yeah, you might have. I've seen some of those use cases in real life where there is a memory leak and you're just observing one element, but you're keep adding intersection observers to the very same element. So that's a memory leak and we should clear that up. If you may notice in my example, there is in that hook, there is a dependency array for watching the reference of an element. So if reference changes, then it's a new intersection observer and we clear the previous one. But if it's the same element, it will always use the same intersection observer. So in that way, we defend against the memory leaks.
And how easy would it be to cover that in testing? Are they all supported in React Testing Library or do you only do end-to-end testing there? Mostly my experience is with end-to-end testing. I don't know exactly how I would do it in Testing Library, but I assume I would mock it somehow, provide some kind of a mock function for the intersection observer. Yeah, OK, cool. Sounds good. I think while we're talking about mocking stuff, how do you treat if a browser does not support the API? OK, that's a very good question. So the first thing I try to do is try to go to the specification and see how it works under the hood. So if it's easy enough to implement it on your own, for example, with the ScreenWakelock API specifically, I had that problem on a project that I needed to solve it for all devices. And there was some kind of a library out there on GitHub, but under the hood, it was trying to use ScreenWakelock API, and if that doesn't work, there was some additional code.
Modifying Code and Browser Support
I was trying to modify the code to our needs and if that doesn't work, I look for the library and its source code to see how it solves the problem. I haven't explored browser implementations yet, but it could be a topic for future talks. Edge has mostly the same support as Chromium-based browsers, around 95% of the time.
So I was trying to modify that code to our custom needs and just trying to make it work. If that doesn't work, then it's OK to try to look for the specific library that is using it and solving the problem. But then again, that library had to do it somehow, right? So then I go to the library and look through the source code of the library and try to find out how the library is solving that very problem.
OK. I mean, it sounds a good way, obviously the source, how they're doing stuff. When doing that, did you also look into the browser implementation of a library just for fun, going into the Firefox or Chromium source?
No, I haven't watched that so far. I haven't had the chance to experience with that kind of example, but afterwards I will definitely do. OK, maybe that's the next talk you can give us. I don't see why not. Let's talk about some specific libraries or specific browsers. Sorry, I misclicked there. How's the support on Edge? I assume it's the same as on Chromium? Yeah, it's mostly the same as Chromium because they use Chromium Engine. So once I showed the Chromium logo, I meant basically Chromium-based browsers. So in my experience, 95% of the time it's the same support for Edge and Chrome.
Comments