1. Introduction to Web APIs and Astronaut Example
Today we're going to talk about Web APIs and their functionalities provided by the browser. We can leverage these built-in interfaces to enhance our web applications. Let's explore some new or not-so-well-known APIs that offer superpowers. I am Nikola Mitrovic, a Development Lead and Software Engineer at Vega IT. In our first example, we have a page with a small astronaut who displays a message when fully visible while scrolling.
Probably this is a classic interview question and if I ask you what is the answer most of you would answer the order of these logs would be 1, 3, 2, right? But how do you know that? How can we know that? So let's visualize this example a bit and check it out.
So as we know, there is a call stack. Our engine starts to execute line by one. Console.log is asynchronous and it's executed immediately, but the set timeout is asynchronous, so it needs to go around a bit. It waits for a number of milliseconds that we put in a callback. It goes in the queue. We wait for the call stack to be free again, and then event loop kicks with the value that we put inside of the callback. But the question is, where does setTimeout wait for those number of milliseconds? And the answer is, WebAPI. If you're a curious engineer as I am, you might ask at that point, OK, what is the WebAPI? And if we Google a bit, we can find out that there is MDN documentation about WebAPI, and the setTimeout is under the tab, WebAPI. If we check there, there we can see that there are a number of available functionalities that browsers offers us out of the box. And if we explore a bit there, we can find a lot of well-known APIs. Like, for example, if you ever built a file upload component, if you ever used geolocation, if you ever communicated with a DOM alters on DOM elements, if you local storage, session storage. So all of those APIs are functionalities that are provided by the browser. Of course, there are some well-known APIs and some well-known functionalities that you're using in day-to-day work. But I was wondering what are some of the new or not-so-well-known APIs that we can leverage in our web applications and really use these super powers? So we can conclude that WebAPI is a collection of those built-in interfaces that we can use just by using the browser.
First, I will just introduce myself quickly. My name is Nikola Mitrovic. I work as a Development Lead and Software Engineer at Vega IT, based in Novi Sad, Serbia. And these are my WebAPI highlights for you for today. We go to our first example for today. So let's say we have an application like this. We have a page. When we scroll down a bit, then we start noticing that there is a small astronaut at the bottom, in the corner. And if we scroll a bit more, once the astronaut is fully visible, he says, Hello World. If we scroll a bit up and the astronaut is not fully visible, the message goes away. If we scroll down a bit again, he again says, Hello World.
2. Using the Intersection Observer API
The Intersection Observer API helps determine if an element is visible on the page by checking if it intersects with the viewport. In React, we can create a hook called UseVisible to observe elements. This hook takes a reference to the element and a configuration object for the Intersection Observer. We can set the margin and threshold for intersection. By setting the threshold to 1, we observe when the element is fully visible. The hook returns a state variable, isVisible, which indicates if the element is visible or not.
Okay, how did we manage to do this? There is an API called Intersection Observer API, which basically figures out if the element is visible on the page or not, if it's intersecting the viewport. If we're doing this inside of a React, we would probably build a hook, lets call it Use Visible and the code looks like this. The hook accepts two parameters, one is the reference of an element that we're trying to observe and there is a configuration object for the Intersection Observer. That configuration object may have the ancestor of the target, if we pass the null, then we are assuming that we are using the viewport as a parent element. We can set up the margin around that element and call that intersection a little bit earlier, and there is a threshold which is a number from 0 to 1. Because we set it to 1, we observe when an element is fully visible, so we can intersect let's say at a half of the visibility. We would have some state isVisible of course, and then we instantiate an intersection observer object. Inside of a callback we would get entry object, and that entry is having a property called isIntersecting. So basically, based on that, we can figure out if element is visible or not, that value would be true or false. What's left to do is just to observe that element. And then at the end, of course, we set the state and returning it back, and we would get from that hook just true or false state.
3. Real-Life Use Cases and Browser Support
We can use the Intersection Observer API in real-life use cases such as lazy loading images, creating infinite scroll lists, and deferring animations. It is important to consider browser support, but in this case, all major vendors support this API.
This example with Astronaut was cute and fun, but you're probably wondering how can we use this API in some real life use cases. We could use it to lazy load images. So for example, we can only load what's important to load initially for the app. And we can offload and lazy load images. Once we scroll back to some certain section that contains images.
We could create infinite scroll lists. So we don't need a library for this. For example, we can have a list of 10 elements and we can have the end of the list element. And once we scroll and that element is visible, it means that we came down to the end of the list and then we can trigger the next request. We could defer some animations. We don't need to run some animations if they are not visible on the screen, and in that sense, we can save some computer power.
One of the things that we should always consider when using some of these web APIs is browser support. So all major vendors support this standard of web APIs, but not all of them are implementing, have that implementation in place. But in this case, we can see that all major vendors support this API, so we're good to go and we can use this and leverage this inside of our web applications.
4. Using the Network API and React Hook
In the next example, we have an app called semirco.rs that communicates with NASA's API to provide a list of habitable exoplanets. We can search for a planet and reserve a flight. The Network API helps us detect system connection changes and react accordingly. By creating a hook called UseNetwork, we can check the connection type and return the state. We can also track network changes and execute state changes. Use cases include user notifications and preloading resources. Chrome-based browsers support this API, but Firefox and Safari do not.
Now we move on to the next example. Here we have a little bit futuristic app called semirco.rs which translated to English means spaceman. It's an app that if we go to in the backend we're communicating with the NASA's API which is returning us the list of all possible exoplanets, habitable exoplanets. And then we can go and search for a planet which we want to visit for a vacation or to enjoy ourselves and for example there is this TOI-1136G, that sounds amazing, we always wanted to go there and then we can click to reserve a flight to that planet. After some time the flight is reserved, but what if we have some connectivity issues? So we try to reserve a flight and that request is taking a bit long. After some time we can display a message to have some better UX or something and once the fast connection kicks in we can move that message away. So note that it's not just about the time of the request, it's also about reacting to the network changes. So how can we do this? There is an API called Network API of course which provides information about the system connection and also detects connection changes that we just seen. If we are building this in React, we would probably make a hook called UseNetwork. We would have the state which represents if the network is fast or not. Then we check for the connection object inside of a navigator. I'm going to get back to this why this is important but if there is a connection object, there is an EffectiveType object on that connection object and then we can check the value of that EffectiveType. The possible values of that EffectiveType are Slow2G, 2G, 3G, and 4G. Then we can assume if it's 4G then, okay it's a fast network, if it's something otherwise, we consider it as a slow network. And we just return that state from the hook. As we noted before, we can also react to the changes to the network. So again we go to the connection object inside of a navigator and add EventListenerChange so we can track those network changes. Once there is a change we can again execute a state change. What are some of the use cases? Of course, some notifications to the users or preloading large resources. This is important for the performance, so we can check if the network connection is fast. If it's fast, then we can preload some bigger resources. Again, if we look at the browser support for these ones. Okay, now here the situation is a little bit different. Chrome-based browsers support this API, but Firefox and Safari are not there yet, so we will have to wait a bit for this API to use it in all browsers.
5. Offline Application and Background Sync
In the next example, we explore the scenario of an offline application. When trying to access a page that triggers a request to the NASA's API, nothing happens if we are offline. However, in the application tab, there is a background sync feature that registers an event when we go back online. This event triggers the request and returns the list of habitable planets.
Okay, moving on to the next one. Again, we have an example with swamirco.rs, but in the previous example, we didn't cover one of the most essential use cases when using today's web applications, and that is what if our application goes offline? I know this is an app a few thousand years in the future, but let's say we still have connectivity issues sometimes. And if we try to go to that page, once we hover over this button, we're triggering the request to the NASA's API. But if we go to the network tab, there's nothing happening. So in normal circumstances, I would expect that there is a network request stunt, which failed, and I would see a red request here that failed. But here we can see that nothing happens. If we try to go to that page, we can see that there is a loader still loading the data, but we know that we're still offline. Interestingly, inside of the application tab there is something called background sync, and once I hover that button, you may notice that there was an event triggered here, and that is a registering event. Once we go back online, there is a dispatch event, and then we trigger the request to the NASA's API. Once the request has finished, then we have a third event called sync completed event, and now we get the list of all habitable planets that we had before.
6. Background Sync API and Offline Capabilities
There is an API called background sync API that allows us to defer tasks in the background while offline. By registering a sync event based on a tag, we can continue with our request once the Service Worker receives the event. This API is useful for offline capabilities and tasks like sending emails. However, Firefox and Safari have limited support for this API.
Okay, how did we manage to do this? There is an API called background sync API, which provides a way to defer some tasks in the background while we are offline into a Service Worker. This is the component that we have on our first page with the link, and once we hover over the link, then we can register that background sync. Inside of a navigator there is a Service Worker object and there is a ready property. Once we get to that registration, then we can register that sync event based on a tag.
Now, this tag is important because we might have multiple events, multiple tasks running in the background while we are offline. And inside of a Service Worker, we just wait for the sync event and we check that tag name. If it's the same, then we continue with our request. Some of the use cases for this API, of course, offline capabilities or maybe if we want to send an email while we are offline, we already clicked the button. Browser support in this case, again, the same as before. We would have to wait a bit for Firefox and Safari to keep up with this.
7. Communication with Broadcast Channel API
To communicate between a Service Worker and our components, we use the Broadcast Channel API. This API allows communication between the same browsing contexts, such as windows, tabs, frames, or iframes. We open a channel, connect to it, and use the postMessage method to send messages. Inside our component, we subscribe to the channel and listen for the onMessage event. This API has various use cases, such as detecting user actions and logging out in all tabs. It is supported by all browsers.
If you're wondering how did we manage to communicate between a Service Worker and our components, in the example before, so once we have established the connection, we would fetch our habitable planet. That would be a request to the NASA's API, and we extract the body from that response. And how did we manage to get that list to the component, to a React component? There is an API called Broadcast Channel API, which basically allows communication between the same browsing contexts, which means same window, tabs, frames, or iframes. The important part is that they are all on the same origin. And it goes two ways, that communication. How can we do that? We open a channel. We connect to a channel based on a name, and then there is a postMessage method on that object to send the message. And we can send any kind of structure or objects. Inside of our component, we subscribe to that very same channel, and there is an onMessage event, which will get us that data. Use cases for this API. We can detect some of the user action, or maybe we can log out in all tabs if we log out in our application. Browser support, in this case, is we're all good.
8. Cool Web APIs and Their Impact
Today we explored some cool APIs like Beacon, Web Speech, Web Share, Screen Awake Lock, Page Visibility, Background Fetch, and Web Authentication. These standardized APIs work across all browsers and can improve performance by reducing the bundle size. It's important to consider browser and device support when using these APIs. Additionally, using web APIs instead of libraries can contribute to a greener web by reducing electricity consumption. Thank you for joining us today!
So we can use this feature inside of all browsers for all users, which is amazing. And since we have a limited time today, unfortunately, we would have to stop. But I'm going to give you some bonus points and I hope I intrigued you enough to investigate some of these cool APIs on your own.
So here are my highlights. There is a Beacon API which basically we use if you want to send a request, but you don't care about the response. The use case is some analytics. There is a Web Speech API, which can figure out our talk and even give us some diagnostics about certain words. There is a Web Share API, which helps us to share data between different devices. There is a Screen Awake Lock API, which prevents us from locking screen on our devices, despite of the personal preferences of that device. There is a Page Visibility API, which figures out if the whole browser, if the whole tab is visible or not. There is a Background Fetch API, which is basically similar to Background Sync, but if we are downloading some large resources and we go offline. And of course, there is a Web Authentication API, which is a brand new, shiny web API for password-less authorization and authentication, of course.