 Hi everyone, my name is Mark Thompson. I'm a developer relations engineer on the Angular team at Google and welcome to my talk. Lately, I've been thinking about user experiences on the web and I've noticed that some of my favorite sites don't work when they're offline and they are slow to load. And if I'm being honest, I can't even be tasked to go to the App Store and download another app. There has to be a solution because this problem isn't new. I want to talk to engineering, but what should I do? I mean, I could tell you or... I think the answer for them is to use a PWA. But if you're going to do a PWA, then really do a PWA. You see, a thoughtful, intentional PWA experience gives you lots of benefits. Giving your users an installable application leads to less friction for your users because, well, they don't have to wait for an app to install or even leave your sites. Having a meaningful offline experience instead of your page just not loading means that users will get the most recently cached information or you can create something to let your users know you are offline. But both of these are vastly better than a generic failure page. You can improve your user's experience with faster load times. There are variety things that developers can do to create fast loading apps such as caching, predictive prefetching and even some architectural patterns. Now, all of these benefits and some others come with choices that are made when creating or converting an application to a PWA. But there's a problem here. This can be a challenging thing to get right. At the core of many of the great things about PWAs is service workers. While service workers are the stars, making service workers can be hard. Let's understand how this part fits and let's chat about service workers for a bit. Let go. This little script in your app can't be beat. If you take advantage, you'll find that it's such a treat. It's double script, so you know it's for me. It could work offline and be your network proxies. You can use it for tasks, but don't get me wrong. You cannot directly access the DOM. I can hear your brain stressing on this. You communicate what the API for messages need to intercept the request on the go. Service workers can do this and now you know. Also, take note that you can grab items that have been stored in the browser's cache. Installing, activated, waiting and idle. These are all part of your workers life cycle. Each state has its place and has its uses. Service workers changing app to useful from use. Okay, we understand a couple of things at this point. Some of our bad web app experiences can be solved with PWAs. At the core of a PWA is the effective use of a service worker. How does an Angular fit into this picture? Well, let's take a look. Angular has first class support for PWAs. This unlocks the potential for us to craft a great PWA experience and not have to focus on which files to set up. To add PWA support to an application, we can use the PWA schematic. To install the schematic, we use ng-add-angular-slash-pwa. Running the schematic makes some important changes to your application. It creates a service worker with the default caching configuration, which we'll look at soon. It creates the web manifest file where things like the app description and icons can be configured. And speaking of icons, the schematic helps us by placing some of the default app icons in the asset folders of our project. And it also does the work to make our application installable. When we first started this talk, the first issue that I mentioned is that well, our applications don't work offline, which hinders our application experience. We solved that problem. By installing the PWA schematic, our application now works offline. To test this out in the application, we first need to build a production bundle using ng-build-prod. Now note, in version 12 of Angular and beyond, the prod flag is deprecated. Yeah! After the bundle is created, we can serve the application with a web server. Remember, you can't use ng-serve here. The next step is to confirm that the application has a service worker. In the application tab in Chrome DevTools, we look at the service worker section to confirm that the service worker is activated. Awesome! This looks great! The service worker is working in action. We can confirm that the application works offline by checking the offline button. And for good measure, I'm going to stop the application server as well. Now I'm going to refresh the page and look at the resources tab to help me identify which of the requests have been intercepted and served by the service worker. Check this out. All of the resources needed to load the page are being loaded. The Angular CLI has turned our app into a PWA. But if I'm being honest, it's all feeling a little magical, right? Well, how is this being configured? Can we figure this out? Well, since you as opposed that we can clear up any doubts. So it's not actually magical. Adding offline support is done when the service worker is installed into your project. Here's one place where we can create a more bespoke experience for our users. Angular supports two types of caching strategy, pre-fetching and lazy. Pre-fetching allows you to specify the assets in your app that should be cached immediately when you run the app with your service worker enabled. But this is going to be bandwidth intensive, especially if you decide to download all of your assets for example. Now, lazy mode only caches the assets when they are requested in app. So if you use this mode, you may find yourself without some assets when in offline mode, but we can actually configure a response for assets that are not available. In the end, you'll want to ask yourself, what do I want my offline experience to be? Then update the cached assets accordingly. A new file called ngswconfig.json is created when the PWA schematic is run. Here's where you can configure the caching strategy as well as determine which assets should be cached. At this point, our application works offline and we're in a great place. Are you excited? Yeah, me too. So get that left hand up because I have something for you. High five. Let's dive into the next phase and that's fast load times. We're going to take this in two parts. There's how fast our application loads and there's boosting data loading speeds in the application. Caching is a recurring theme in our story today and it's going to make an appearance again. In most applications, there are parts that only change with the major redesign. This may be a header, footer or navigation menu. Because these don't change frequently, what if we can load them while we load the rest of our app and dynamic content? The users wouldn't be able to tell that every time they visited, there was a quickly loading shell. Separate concerns and take advantage of routes. That way, we'll load the data that they care about and for us, that means that pages load snapping you quick. First contemplate comes right before the clicks. And this is legit because we crave interaction. Fast load times means more satisfaction. And don't stress this implementation. Use the Angular CLI for your asset generation. Okay. The App Shell architecture allows for the quick load and app-like experience in your PWA. The architecture isn't unique to Angular, but we get to take advantage of the CLI to enable it. So the core idea behind the App Shell architecture is to provide some minimum HTML and CSS to get to a meaningful first contentful paint by loading some content instantly. So what's a good candidate for you to include in your App Shell? Well, here I like to consider headers, footers, and even potentially some navigation items that don't change often. The goal for the user is to land on your page and be immediately shown some content to create that instant load effect. It appears to be instant because we can take advantage of caching again with the mighty service workers. In Angular, we use the CLI to generate the App Shell. We run the ngg App Shell command to kick off the process. This will create a new component for us to structure as a placeholder content that users will see when the application is progressively loaded. When things are cached properly, the load even offline will be instant. Once we've added the HTML and CSS we want to appear in our App Shell component, we'll then generate a production bundle that'll create the necessary assets. Using ng run myapp app-shell, that starts the process. Here, you replace my app with the name of the app that you want to run this against. To see the App Shell loading, I'm going to load the app with an HTTP server. In this slowed down clip, we can see the App Shell loading instantly, then the full app loading. Here's another question. Can we speed up things once our app is loaded? Well, the answer is yes. The service worker config file has a section dedicated to data called data groups. This is where we can specify which API is to cache as well as how long they should stick around in our app. And we get to define what's the best strategy to use. There's a lot of configuration available here. There's API version, in case there are some compatibility issues that you need to be mindful of. There's a timeout to specify how long should the service worker wait before timing out on a request and looking at the cache. And then there's a really interesting strategy property. The choices are performance and freshness. Performance prefers choosing the cache version of a resource before making a network request. And then there's freshness. This strategy prefers making a request over the network before considering your cache. Now, you'll risk stale data in performance mode, but may experience slower response times and freshness mode. Again, use this opportunity to make strategic choices. If you have data that doesn't change often, like a department list, well, this is a great candidate for performance strategy. But if you have something like stock prices, well, you can't risk stale data, so you should likely choose freshness for these types of resources. Okay, so far we've tackled offline ability and faster load times. But at the start of our conversation, we identified one more point of friction that our users face. Sometimes web apps will encourage the user to install a separate application. Now, I know this works, but sometimes it isn't optimal. You see, the user is already interacting with your web app. Having a separate application makes sense when you need to create an experience that's just not possible on the web. But if you're having a hard time trying to identify what that could be, well, that's a good thing because the web is incredible and the APIs are becoming more and more robust. The web continues to move forward as more features are adopted by the major browsers. PWAs are installable once you've added support for them in your application. The workflow for the user isn't a stretch for your imagination. Well, here we are friends and we're ready to put the finishing touches on our application. One of the final pieces is the SW update service that's made available to your application. The service gives you access to events that let your application know things like if an update is discovered for your app or when the update is actually been activated. This is very useful information that we can take advantage of because, well, it allows us to customize our PWA experience for the user. There are four separate operations that we can tap into. Getting notified of available updates for your application. So these are the ones that will be loaded when the app refreshes. We can be notified of update activation, meaning that the service worker has started serving a new version of your application. We can even ask service worker to check the remote server for updates. And we can ask the service worker to activate the latest version of our app in the current tab. Now, two of these events are observable, available and updated. So we can tie in our custom logic here in our application. Which, as you might be thinking, can include functionality like displaying a ToeStyle message or even triggering a push notification. There's a service worker object for interacting with push notifications called SW push. Including this in your app will allow you to build out these types of features for your application. Finally, to make our app installable for all users, we can use a service like Firebase hosting. Using the Firebase schematic, we can add our Firebase tool with our app, select the current project and then deploy our app using ngDeploy. Then it'll be live and ready for everyone to see. Alright friends, this has been an incredible journey together. We see how to take our standard web experiences and make them more meaningful and intentional for our users through the use of making the app work offline with service workers, speeding up load times with caching and the app cell and making a more app-like experience when installed by integrating the services provided by Angular. So what's next? Well, go build great apps. Thank you.