Duration 34:42
16+
Play
Video

Beyond single page apps: alternative architectures for your PWA

Jeffrey Posnick
Software Engineer at Google
  • Video
  • Table of contents
  • Video
2018 Google I/O
May 9, 2018, Mountain View, USA
2018 Google I/O
Video
Beyond single page apps: alternative architectures for your PWA
Available
In cart
Free
Free
Free
Free
Free
Free
Add to favorites
25.25 K
I like 0
I dislike 0
Available
In cart
Free
Free
Free
Free
Free
Free
  • Description
  • Transcript
  • Discussion

About speaker

Jeffrey Posnick
Software Engineer at Google

Jeff is a member of Google's Web Developer Relations team, where he builds libraries that take the work out of using service workers.

View the profile

About the talk

Building a Progressive Web App (PWA) doesn't mean building a single page app! This session will deep-dive into alternative architectures for content-focused PWAs, and help you make the right decision for your specific use case. You'll also get insights on how the Workbox project provides developers with an easy path towards using the web platform features that provide the foundation for these architectures.

Share

So hello everybody. Hey, my name is Jeff poznick. And I'm a member of Google developer relations team. So I'm here to talk about an important but potentially misunderstood topic. The architecture that you use for your web app and specifically how your architectural decisions come into play when you're building a progressive web app. So what do I mean by web architecture? Well one way to think about it is ask yourself the following questions. What are user visits a page of my sight what HTML is loaded?

And then what's loaded when they visit another pitch? The answers to those questions are not as straightforward. And once I start thinking about Progressive web apps they can get even more complicated. So my goal during the session is to walk you through one possible architecture that I found effective. Throughout the talk. I'll label the decisions that I made as being my Approach for building Progressive web app. You're free to use my Approach when building your own TWA. But at the same time they're always other valid Alternatives as well. My Hope Is

that spicy how all the pieces fit together one Spire you and that you will feel empowered to go out and customize everything to suit your own particular needs So what are you doing Building C company? This talk is a stack overflow pwi. I personally spent a lot of time reading and also contributing to stack Overflow and easy to browse through frequently asked questions for a given topic. It's built on top of the public stack exchange API and you can try it out live and view The Source Code by using the Euros on

that slide. It's a before, you know, the specifics how I built that web app. Let's define some terms and explain pieces of underlying technology. 1st and B talking about what I like to call multi-page apps or MPS. Do you think of npas as a fancy name for the traditional architecture that's been used really since the beginning of the web? Each time a user navigates to new RL the browser progressively renders HTML specific to that page. There's no attempts to

preserve the page of states or the content in between navigations. Each time. You visit a new page. You're starting fresh. This is in contrast the single page app model for building web apps browser runs JavaScript code to update existing page when the user visits a new section. And both SPS and empieze are equally valid models freaky for you to use. But for this talk, I wanted to explore pwa Concepts within the context of a multi-page at some point. We haven't really talked about too much in the past.

The next. You've heard me and certainly countless others use the phrase Progressive web app or pwa. But what do I mean by that exactly? So you can think of a pwa as a web app that provides a first-class user experience and that truly are in some place on a user's home screen. The acronym fire standing for fast integrated reliable and engaging sums up all the attributes to think about when you're building a pwa. The purposes of this talk. However, we're going to focus on a subset of those attributes fast and reliable. A

fast means a lot of things in different contexts. We're going to focus on the speed benefits of eluding as little as possible from the network. The raw speed isn't enough in order to feel like a pwa your web app should be reliable. Mystery resilience enough to always load something even if it's just a customizer page regardless of the state of the network. And finally, we're going to rephrase the pwa definition slightly and look at it what it means to be reliably fast. That's not good enough

to be fast and reliable only when you're on a low latency Network. Being reliable fast means your web app speed is consistent regardless of the underlying that were conditions. Cpwa has introduced a high bar for Speed and resilience. Fortunately the web platform offer some building blocks to make that type of performance reality. I'm talking of course about service workers and the cache storage API. So a service worker sits in between your web application and the network acting as

a proxy that could intercept incoming requests. And what that service worker does is completely up to you. And it's basically stration the service worker takes incoming requests and froze amounts of network. Avengers returns to never responds to page as is It was trivial service worker doesn't actually add any value versus the default number Behavior. But once we add the cache storage API into the mix the power of service workers shine through. So we can build a service worker that listens for incoming requests like before. Passing some on to

the network. Instead of just returning the network response to the page. We could write a service worker that stores a copy of the response for future use me the cache storage API. Next time or web app makes the same request our service worker can check its caches. And just return the previously cash response. Avoiding the network whenever possible is a crucial part of offering reliably fast for formance. When were Concepts that I want to cover is what sometimes referred to as isomorphic or Universal JavaScript? If it's not a great name for it, simply put it's the

idea that the same JavaScript code can be shared between different runtime environments. So when I build my pwa I wanted to share JavaScript code between my back and server and the service worker. Are lots of valid approaches to Sharon code in this way, but the person at work for me was to use es modules as a definitive source code. Ivan transpile din bundle those modules for the server and for the service worker using a combination of Babel and roll up. Send my slides when you see an M JS file

extension for taking a code that lives in an e s module. So keeping those Concepts and terminology mines, let's dive until I actually built my stack overflow pwi. Remastered by covering a back-end server and explain how that fits into the overall architecture. So is looking for combination of nighttime Dynamic Falcons along the static hosting and my personal approach was used to Firebase platform. Firebase Cloud functions will automatically spin up a nude based environment when there's an incoming requests and integrates with the popular Express h-2b framework, which is already familiar with

It also offers out-of-the-box hosting for all of my sight static assets. And let's take a look at how that server handles incoming requests. So when browser makes a navigation request against our server and goes through the following flu the server routes the request based on the URL and logic to complete to create a complete HTML documents. Music combination of data from the stock exchange API as well as partial HTML fragments that the server stores locally.

So once we know how to respond we start streaming HTML back to our web app. Sochi pieces of picture worth exploring in more detail routing and templating when it comes to writing my Approach was he used to express Frameworks native routing syntax. It's flexible enough to match simple URL prefixes as well as euros and sleep remedies such as you know, the question ID as part of the path. As mentioned earlier were using ES modules as a source of Truth for my isomorphic JavaScript code. Here we create a mapping between route names and the underlying Express

pattern to match against. I can reference this mapping directly from the service code. when there's a match for a given Express pattern the appropriate Handler with template in logic specific to the matching rabbit is given a chance to respond. And what is that templating logic look like? Well, I want with an approach that piece together. Partially. It's no fragments in sequence one after another. This model lends itself really well to streaming response back to the browser.

The service sends back some initial HTML boilerplate immediately and the browser's able to reminder that partial cage right away. As a server pieces together the rest of the data sources and streams them to the browser as well until the documents is complete. 303 what I mean, let's take a look at the express code from one of our routes. Are using the responses right method and referencing locally-stored partial templates were able to start the response stream immediately without

blocking on any sort of external data source. So the browser takes this initial HTML and renders a meaningful interface and loading messages right away. So that loading please wait message gives important context to our users, but it's not the sort of thing that you might expect to see in a multi-page out. Rather than rely on JavaScript. I'm using the empty pseudo-class in the pages CSS to display the message. And then it'll automatically disappear once a real content start streaming in.

It's going back to her route Handler. The next portion of our page uses data from the stock exchange API. Getting that data means that our server needs to make an egg a network request. We can't render anything else cuz we got a response back and process it. But at least our users and staring at a blank screen while they wait. And once we received the response from the stack exchange API, we call a custom template in function to translate the data from the API into its corresponding HTML.

The temp setting can be a surprisingly contentious topic and what I'm presenting here is just one approach among many. You'll definitely want a substitute and your own solution here, especially if you have Legacy ties to an existing templating framework. But we made sense for my use case was to just rely on JavaScript template literals with some logic Broken Out In to help her functions. So one of the nice things about building an MPA is that we don't have to keep track of State updates and rear under a female as things change.

So basic approach that produce static HTML work fine for me. Alright, so here's an example of how I'm template in the dynamic HTML portion of a web apps index. That's what our routes the template in logic is stored in an es module that can be imported into both the server and the service worker. And just a reminder when your whenever you're taking user-provided input and converting into HTML. It's crucial that you take care to properly Escape potentially

dangerous character sequences if using an existing template in solution rather than rolling your own that might already be taken care of for you. Okay, so these template functions are pure JavaScript and C is for the break out the logic and smaller help her functions when appropriate. Here I passed each of the items returned in the API response in someone such function. Which grapes is standard HTML element with all the appropriate attributes set? A particular notes is a data attribute and we had to

each link set to the stack exchange API Euro that we need in order to display the corresponding question. Keep our minds will Revisited later on? Okay, so jumping back to a route Handler. Once templating is complete we stream the final portion of a Page's HTML to the browser and we end the Stream. This is a key to the browser that the progressive rendering is complete. Okay, so that's a brief tour of our server setup. Users who visit our web app for the first time but always got a response from the server, but

when to visit visitor returns to our web app, our service worker will get a chance to start responding and what's time in there? Instagram she looks somewhat familiar many of the same pieces. We've previously talked about our here in slightly different arrangement. Let's walk through the request for for the service worker taking all of its logic into account. Their service worker handles and incoming navigation request for giving you oral. And just like a server did it has to use a combination of routing and templating logic to

figure out how to response. Approaches the same as before, but with different low-level Primitives like thatch and the cache storage API. We use those data sources to construct or HTML response, which the service worker passes back to a web page. So rather than starting from scratch with those low-level Primitives, we're giving a builder service worker on top of a high-level set of high-level libraries old work-box. So I'm a member of the workbox engineering team and this is not exactly unbiased but I think using workbox provides a solid foundation for any service workers cashing

routing and response generation logic. Brett the next time slides. We'll see how work box is put to use. First let's cover service worker routing. Justice Weather Service, I'd code or service worker needs to know how to match up an incoming request for the appropriate response logic. My Approach was the translate each express route into a corresponding regular expression making use of a helpful Library called regex program. Once I translations performs, we can take advantage

of work boxes built-in support for regular expression routing. So after importing the module that has our regular Expressions, we register each one with work boxes router. Inside each route. We're able to provide custom template in logic used to generate a response. Templating in the service worker is a bit more involved than it was in her back end server of work box helps with a lot of the heavy lifting. The first we need to make sure that are partial

HTML templates are locally available in the cache storage API. And are always kept up-to-date whenever we deploy changes to a web app. Couch maintenance can be are prone when done by hand. So we trying to work box to handle pre cashing as part of a build process. Retail workbox which euros and free cash using a configuration file pointing to the directory that contains all of our local assets along with the set of patterns to match. This file is automatically read by the workbox CLI, which is run each time. We rebuild our

sites as part of my build process. So workbox takes a snapshot of each files contents and automatically injects that list of euros and revisions into a final service worker file. Workbox now has everything it needs to make sure our pre cash flows are always available and always kept up to date. Prefer to use more complex build process where each box has both of webpack as well as a generic node module interface in addition to his command line. What's the next we want

a service workers stream that precache partial HMO back to the web app immediately without any delays. This is a really crucial parts of being reliably fast. We always get something meaningful on the screen right away. Fortunately using the streams API within our service worker makes a possible. No, you might have heard about the streams API before my colleague. Jake Archibald has been singing the Praises for years now made this bold prediction back in 2016. And the

streams API is just as awesome today as it was two years ago Over The crucial difference. One week room supported the streams back. Then the streams API is much more widely supported now. I so know careful observers my note that asterisk. So here are the caveats for today. Firefox's worth of streams is behind a flag, and it's not yet enable by 50 falls, but you can try it out if you go in and manually make that change. And it's also a known bug that lead to issues with edges current streams implementation. But the overall story is positive and

with appropriate fallback code. There's nothing stopping you from using streams in your service worker today. Well, there might be one thing stopping you and that's wrapping your head around how the streams API actually works. Expenses a very powerful set of Primitives and developers who are comfortable using it can create really complex data flows. But understanding that the full implications of code similar to what's on the screen right now might not be for everyone. Rather than parse through this logic. Let's talk about

my approach to service worker streaming. So I'm using a brand new high-level rapper provided by workbox. I can pass it in a mixer stream sources what from caches and runtime data that might come from the network. Workbox will take care of coordinating the individual sources and stitching them together into a single streaming response. Moreover workbox automatically detects whether the streams API supported and when it's not it creates an equivalence Zone on streaming response.

This means that you don't have to worry about writing fullbacks as streams inch closer to 100% browser support. Alright, let's turn our attention to how our service worker deals with run time data from the stack exchange API. So we're making used to work boxes built-in support for a Stihl while rebelde cash and strategy. Long with expiration to ensure their storage doesn't grow unbounded. Let's take a look at how those Concepts translate into code. here we set up two strategies and work box and handle the different

sources. They'll make up the final streaming response. If you function calls and some configuration workbox, lets us do what would otherwise take hundreds or even thousands of lines of handwritten code. For the first strategy will be used to read data that's been pretty cashed like a partial HTML templates. The other strategy implements that still while we validate cashing logic along with the least recently used cache expiration once you reach 50 entries. Now that we have the

strategy someplace all that's left is to tell work box how to use them to construct a complete streaming response. A pass in an array of sources as functions and each of those functions will be executed immediately. Workbox takes result from each source and streams it to the web app in sequence only delaying if the next function in ear a hasn't completed yet. So the first two sources are Precast partial templates that read directly from the cache storage API and so they'll always be available immediately.

This ensures that our service worker implementation will be reliably fast and responding to requests just like our server side code was Arnex, quartz function fetches data from the stack exchange API and processes response is the HTML that are webapp expects. The still well-regarded strategy means that we have a previously cash response for this API call will be able to stream it to the page immediately while updating the cash entry in the backgrounds for the next time that it's requested.

Finally we stream in a cached copy of our footer and close our final HTML tags to complete the response. So now we run through the service worker code certain bits. Hopefully look familiar. The partially Sumo and sampling logic used by a service worker Is identical Twitter cervicide Handler uses? This code sharing and sure is that users get a consistent experience whether they're visiting or at web for the first time or if they're returning to a page

that's been rendered by the service worker. That's the beauty of using isomorphic JavaScript. Okay, so we walked through both the server and a service worker for a pwa. There's one last bit of logic to cover. There's a small amount of JavaScript there runs on each of her Pages after they're fully streamed in. This code for aggressively enhances the user experience, but it isn't crucial the web Apple still work if it's not run. The one thing we're using client-side JavaScript for is to update a page is metadata based on the API

response. Because we end up using the same initial bit of cash HTML for each page. We end up with generic tags in our documents head. Better coordination with between are templating and our clients I'd code we can update the windows title using page specific metadata. So is part of the templin code include a script tag containing the properly Escape string? Then once our page has loaded we read in that string and we update the document title. If there are other pieces of page specific medidata, you want to update in your own web app. You

can follow the same approach. So the other Progressive enhancement we've added is used to bring attention to our offline capabilities. We built a reliable pwa and we want our users to know that when they're offline. They could still load previously visited pages. Would you listen to stages? First we use the cache storage API for within the context of a client-side JavaScript. It gives us a list of all the previously cashed API requests and we translate that into a list of urls.

Remember the special data attribute. We talked about containing the URL for the API request needed to display a question. So we could cross-reference those data attributes against the list of cash URLs and create an array of all the question links that don't match. This gives us all the data. We need to create handlers that responds to the browser going online or offline. Tsuna brother interest in offline States. We Loop through the list of uncashed links and dim out the ones that won't work. So keep in mind that this

is just a visual hints to the user about what they should expect from those pages. We're not actually disabling. The links are preventing the user from navigating. I want to browser comes back online. We restore those links to their original paths today. I have is now going through a tour of my approach to building a multi-page pwa. There's a lot of factors that you'll have to consider when coming up with your own approach and you may end up making different choices and I did and that flexibility is one of the great things about building for the

web. But there are few common pitfalls that you may encounter when making your own architectural decisions, and I wanted to call them out in advance to hopefully save you some pan. So first, I really recommend against storing complete HTML documents in your cash. for one thing it's a waste of space your web app uses the same basic educational structure for each of its Pages you end up storing copies of the same mark up again and again, More importantly though. Let's see you to play

change your sites shared if she male structure. Each one of those previously cached pages is still stuck with your old layouts. You can imagine the frustration when returned visitors come back and see mix of old and new pages depending upon whether they've previously visited a given URL. So the other Pitfall to avoid involves your server and your service worker getting out of sync. My Approach was use isomorphic JavaScript so that the same code was always run in both places. But depending on your existing server architecture,

that's not always possible. Whatever architectural decision you end up making you need to have some strategy for running the equivalent routing and templin code in your server and your server work service worker. So what happens when you ignore those pitfalls? Mom, also it's all sorts of failures are possible. But the worst case scenario is that a user returns your site and navigate to rounds? Eventually reversing a cached page for the very stale layouts.

So it's jarring when you see it happen during a presentation and it's just as distracting for your web apps repeat visitors. So do everything you can to avoid this. Alternatively, they might come across the URL that's handled by your server. But is no longer handled by your service worker. Experience full of zombie layouts and routing dead-ends is the opposite of shipping a reliable pwa. But you're not in this alone. The following tips to help you avoid those pitfalls. Try to use templating and routing libraries that have

JavaScript implementations. Now, I know that not every developer has a luxury of migrating off your current web server and templating language. But a number popper template popular templating and routing Frameworks have implementations in multiple languages. You can find one that works with JavaScript as well as your current service language. You're one step closer to keeping your service worker in your server in sync. Next I recommend using a series of sequential templates that could be streamed in one right after another. It's okay. If later

portions of your page use more complicated template and logic as long as you can stream in the initial parts of your HTML as quickly as possible. Best performance. You should precache all of your sites critical static resources. the sausage stuffer run time Cashing routes to handle Dynamic content API requests using workbox means that you can build on top of well-tested production-ready strategies instead of implementing it all from scratch. And related to that you should only block on the network when it's not possible to stream a response from the cash.

Displaying a cached API response immediately can often lead to a better user experience than waiting for that fresh data. If you follow the general guidelines that have covers today you're on your way to building a first-class pwa experience. Experience of fast learning as little as possible from the network and the case my stackoverflow pwa almost all the bikes were looting or for actual contents with almost no overhead. I'm building an experience that's reliable, but it's playing something meaningful even when you're offline.

Are pwa uses visual cues to reinforce that we're providing reliable experience. An experience that's reliable fast by streaming in our initial issue immediately. followed by Page specific content regardless of a network conditions that about wraps it up for me were interested in your feedback on this presentation. Please go to our website or use the Android or iOS apps. Let us know what you think. And if you want to learn more about the topics covered these links will help. So thanks everybody for watching. Thank you.

Cackle comments for the website

Buy this talk

Access to the talk “Beyond single page apps: alternative architectures for your PWA”
Available
In cart
Free
Free
Free
Free
Free
Free

Access to all the recordings of the event

Get access to all videos “2018 Google I/O”
Available
In cart
Free
Free
Free
Free
Free
Free
Ticket

Interested in topic “Software development”?

You might be interested in videos from this event

September 28, 2018
Moscow
16
159
app store, apps, development, google play, mobile, soft

Similar talks

Michael Bleigh
Software Engineer at Google
Available
In cart
Free
Free
Free
Free
Free
Free
Steve Orvell
Software Engineer at Google
Available
In cart
Free
Free
Free
Free
Free
Free
Eric Bidelman
Senior Staff Developer Programs Engineer at Google
Available
In cart
Free
Free
Free
Free
Free
Free

Buy this video

Video

Access to the talk “Beyond single page apps: alternative architectures for your PWA”
Available
In cart
Free
Free
Free
Free
Free
Free

Conference Cast

With ConferenceCast.tv, you get access to our library of the world's best conference talks.

Conference Cast
558 conferences
22059 speakers
8245 hours of content