Dimitri Glazkov, Alex Komoroske, and I started the project that designed and (for many years) iterated on Web Components with a few primary goals in mind:
Enhance component portability
Shrink the amount of infrastructure code required over-the-wire and at runtime
Enable the browser to optimize components
All of this was wrapped up in our project's mantra: "say what you mean".
Web developers shouldn't need build steps or an expensive runtime systems to re-create parsing. Nor should typing <tree-control> in your markup require a specific framework to "fake" parser integration with custom, per-framework timing and lifecycle management (a source of much incompatibility).
None of them could meaningfully share components or code.
Each of these tools became inadvertently totalizing when used at scale. The cost of the framework code was a major concern, and pulling in components from different frameworks implied pulling in all of the support code required to bootstrap the component models of each system. Maybe that would be palatable for a particularly juicy component (data grid, anyone?), but interop was more frequently stymied by the need to wrap components. The decision of which abstraction to interoperate on implicitly creates a situation where teams must pick "their" framework and then make components from other systems work within those terms.
It doesn't take a lot of familiarity with the history of JS frameworks to note a wide diversity amongst successful tools on a number of important axes: the most productive and efficient way to instantiate components, how and when configuration takes place, how data and configuration are updated, the lifecycle of the component, ownership of (and access to) managed DOM nodes, markup integration, and much more. Templating systems are relatively pluggable, but the thing about frameworks is that they set the terms of everything that happens in components. When frameworks make different choices (and they do), compatibility is the first casualty.
At this drilled-in level, we will no doubt endlessly debate these choices. Businesses trying to make durable investments, however, are forgiven for growing weary of the predictable outcomes: teams decide on the "best" tool, invest heavily in building (or using) components, only to discover that the next app or the next team makes a different choice. This creates a compatibility quandary as soon as anyone wants to re-use anything. Just upgrading from Version N of a framework to Version N+1 frequently creates this sort of problem. The painstaking work of building accessibility, shared styles, and reasonable performance into components often looks like good money after bad.
There are also costs associated with compatibility. First, compatibility requires stability and a commitment to a specific design. This ham-strings framework authors who (rightly) value the ability to change their minds and adapt to better ways of approaching problems. Second, the overhead of compatibility testing for the matrix of frameworks detracts from other priorities (performance, accessibility, "developer experience") that frameworks are judged on; particularly at adoption time. Where would this time-consuming work take place? Conference calls? How often? Who's organising and paying for it?
The logical tree of high-level components ("widgets") which developers use to construct their applications
An internal tree of managed DOM for each widget
Frameworks are in the business of providing the abstraction for the logical tree, a system for creating and managing widget internals, and (most importantly), systems for preventing widget internals from leaking into the logical tree. Until now, the only game in town for creating this encapsulation has been to create a tree that's parallel to the one exposed in the DOM.
Before the arrival of Shadow DOM, there was no way to avoid airing all of a component's dirty laundry (managed DOM) in the overall tree structure of the document. Component authors need to operate on the bits of DOM that they "own" and manage, whereas component users usually want to avoid seeing, touching, or interfering with the implementation details of the components they're composing into an app.
Custom Elements and Shadow DOM eliminate the need for a separate tree and traversal system. Together, they allow the developer to surface their component as a first-class citizen within the existing contract (HTML and the resulting DOM) whilst hiding the implementation details from casual traversal and interference. This is a trick that the built-in elements (think <video> or <select>) have been able to do forever, but until now it has not been available to us muggles.
Web Components represent something fundamentally different from the status quo. No other approach is able to actually eliminate the need for parallel trees.
The kicker is that Web Components are a web standard. The half-decade argument about what the lifecycle methods should be called, what they should do, and how it should all fit together has concluded. What's shipping in Chrome and Safari and Opera and Samsung Internet and UC Browser today is not something that can change easily (for better and for worse). This is a contract that a major fraction of the web relies on; it cannot be removed. The browsers that haven't shipped yet are under hugepressure to do so.
In the talk I gave a few weeks back at the Polymer Summit, I went into detail about the performance motivations for some of the original Parkour work:
One of the best outcomes from delegating our component model to the platform is that, when we do, many things get cheaper. Not only can we throw out the code to create and manage separate trees, browsers will increasingly compete on performance for apps structured this way. Work over the past year in Chromium has already yielded significant speedups for Custom Elements and Shadow DOM, with more on the way. Platform-level scoping for CSS via Shadow DOM has enabled sizable memory and compute wins for style resolution, and overall re-architecture of the system benefits custom elements in ways that user-space won't benefit from as significantly.
Ignoring all of that, Mikeal's core point resonates strongly:
Our default workflow has been complicated by the needs of large web applications. These applications are important but they aren’t representative of everything we do on the web, and as we complicate these workflows we also complicate educating and on-boarding new web developers.
One of the things we'd hoped to enable via Web Components was a return to ctrl-r web development. At some scale we all need tools to help cope with code size, application structure, and more. But the tender, loving maintenance of babel and webpack and NPM configurations that represents a huge part of "front end development" today seems...punitive. None of this should be necessary when developing or using one (or a few) components. Composing things shouldn't be this hard. The sophistication of the tools should be proportional to complexity of problem at hand. Without a common component model, that will never be possible.
Since Frances and I published a blog post last year introducing Progressive Web Apps, a healthy conversation has started about what is and isn't a PWA. There are a lot of opinions and many shades of gray. What are the hard requirements? Which requirements are marginal? What's aspirational? This article outlines these requirements, attempts to classify them, and provides a baseline for "what is a Progressive Web App?"
Browsers gate Progressive Web App installation prompting and badging on criteria that they detect when users navigate to sites. These criteria have been designed to ensure that sites which invoke prompts are reliable, fast, and engaging.
In January 2015 I designed the criteria that Chrome uses to trigger "Add to Homescreen" prompts. These prompts are what let users know that a site is a Progressive Web App. Sites that earn a spot on the homescreen report increased long-term engagement with these users.
Questions remain about what criteria browsers should enforce to gate prompting; that conversation is healthy, but this article isn't a contribution to it. Similarly, per-browser criteria are not cataloged. Instead, this article focuses on the strictest common criteria to ensure broad installability as of late 2016. Proprietary and legacy technologies (e.g., AppCache) are also out of scope as they don't contribute to prompting. This article is a time-capsule. The set of things you need to do today to cause your site to be recognized by browsers and bots as an installable Progressive Web App.
In general, installability criteria are tightening. Today's Good-To-Haves may become part of tomorrow's baseline. The opposite is unlikely because at least one major browser has made a strong commitment to tightening up the rules for installability.
A Progressive Web App is functionally defined by the technical properties that allow the browser to detect that the site meets certain criteria and is worthy of being added to the homescreen. These criteria are motivated by user-experience concerns. Apps on the homescreen:
Should load instantly, regardless of network state. This isn't to say that they need to function fully offline, but they must put their own UI on screen without requiring a network round trip.
Should be tied in the user's mind to where they came from. The brand or site behind the app shouldn't be a mystery.
Can run without extra browser chrome (e.g., the URL bar). This is a potentially dangerous permission. To prevent hijacking by captive portals (and worse), apps must be loaded over TLS connections.
These concerns give rise to today's Baseline Criteria. To be a Progressive Web App, a site must:
Some criteria are situational or specific to particular form-factors. For example, an immersive game may need to run full-screen and may only want to work in a single orientation. That set of choices is an anti-pattern for a news app. Similarly, not every app needs to send users Push Notifications. This means that the following should be thought of as a score over-and-above the lowest passing grade. In US educational terms, doing well in these criteria will be the difference between a C- and an A-:
From correct viewport specification to tap-target size, it's important that PWAs work well across form factors and screen sizes. Responsive Design can reduce the time and effort required to achieve this.
Progressive Web Apps should be interactive (loaded and free of long-running scripts) in less than 5 seconds on a representative connection on a representative device (see below) before a Service Worker is installed.
Once the Service Worker is active, apps should load (be interactive) in less than a 2 seconds. This should not vary with network state.
Work across devices & browsers.
A well-built site must work for 90+% of all users in its market.
While Progressive Enhancement is ideal, it's possible to meet this requirement with multiple versions, although having multiple domains (e.g. "m.*") is something to avoid if possible.
Great UIs take effort to build and polish, but the results can be incredible both for users and businesses. Frameworks are starting to adapt to these demands, e.g. the PRPL pattern and similar architectures for high-performance app loading, making it easier than ever to deliver amazing experiences on the web that hit all of the PWA high notes.
Verifying that your PWA meets some of most of these criteria, specifically the baseline requirements, has required a great deal of manual testing…until recently. Thanks to the new Lighthouse project, it's possible to automate checks for many of these properties. You can even integrate Lighthouse into continuous integration systems to catch regressions.
DevTools are also improving rapidly to help you see the impact of changes. The new Security and Applications tabs allow quick diagnosis of common gotchas at development time.
Building a high-quality Progressive Web App has incredible benefits. A great experience can delight users and improve business outcomes. A bit of up-front planning, on-device testing, and iteration with Lighthouse can make it easier to realise them.
A primary issue is the broad diversity in network and device performance. Developers tend to own devices (both desktop and mobile) that are significantly faster than the devices their apps will be experienced on. Many developers I've spoken with have never used chrome://inspect. They are frequently surprised to find their applications to be unacceptably slow on real phones.
To avoid this, it's imperative to be testing on real phones. But which ones? In an ideal world, automated testing of real-world performance would be trivially available in our continuous integration systems. Lighthouse attempts to emulate some aspects of mobile devices to provide actionable insight, but teams who are striving for A+ status need mid-tier devices to verify these results on.
Which ones to buy? The answer is market-dependent. The broader a service's reach, the lower-end the target phone should be. Networks also differ by market. "3G" often means something wildly different in practice in different geographies and even when users may have access to LTE service in theory, changing network conditions frequently put users into slower connections.
In late 2016, the following phones & testing settings strike a decent balance for their markets:
These recommendations attempt to be middle-of-the road in terms of price and capability. If your team is going for the best possible experience, don't be afraid to standardise on cheaper or older devices!
In the case of Chrome it encourages web app developers to build using newer Web Technology such as Service Workers and Web App manifest. It is great because it encourages the building of Web Apps as opposed to native by greatly reducing the barrier to getting your company’s app on the user’s home screen.
Andrew called this a "bag of carrots" and he's not entirely wrong. When I designed the heuristics that Chrome uses to designate something worthy of prompting it was with the user values of reliable performance, ease of recall, and long-term security in mind. Any site can continue to live all its days in a tab; nothing is taken away from that mode. PWAs are about adding new capabilities to existing ones.
The browser's goal is clear: create a hurdle tall enough that only sites that meet user expectations of "appyness" will be prompted for. Maybe Chrome's version of this isn't great! Feedback like Ada's, Andrew's, and Jeremy's is helpful in letting us know how to improve. Thankfully, in most of the cases flagged so far, we've anticipated the concerns but maybe haven't communicated our thinking as well as we should have. This is entirely my fault. This post is my pennance.
Prompting: The First, Worst Guess
The prompting solution to PWA discovery was our first, worst guess at how to communicate to users that they are on a site that can act like an app. Despite the prompt's defects, it bootstrapped what we now think of as "Progressive Web Apps" with Chrome, Samsung Internet, and Opera all implementing versions of it in their Android browsers (note: no browser on iOS supports this as Apple [prevents meaningful competition]).
Getting just this much done was an enormous lift. The team had to overcome organisational skepticism that, bluntly, was daunting. Like "when this is all over I'll write a book and it will not be a comedy" daunting. If you think Google is a one big happy family or has "A Plan (TM)"...um...well...I encourage you to apply! They can't fire me for encouraging smart folks to work here, right? Regardless, we pulled it off. But an early first attempt, no matter how difficult, isn't going to be where PWA discovery ends.
Obviously I can't talk about what Chrome will or won't ship -- I have neither the power nor the crystal ball required to make statements like that -- but I can outline a few alternatives to the current "go to example.com, use it for a while, do a jig, pray for the prompt" approach to PWA discovery. I'll also take a moment to cover some of the FAQs about the current design, including Ada's.
"Engaged-user prompting" is the current (and in Chrome today, only) way to discover that a site you're on is a Progressive Web App. Remy recently noted why it wasn't a crisis that this doesn't mirror app-store listing: the main action that users need to perform to discover the content is the same thing they do to use the site/service. Progressive Web Apps cut out the App Store middle-man. If you can convince a user to visit your site, you have an opportunity to help them engage with your service. The prompt builds on that engagement and lets users who are engaged choose to keep the experience to the homescreen, where it can then launch in a more immersive mode.
Alone, though, this has major drawbacks.
First, users have been trained for the past decade to look for "apps" in App Stores and might not understand the install prompt. This is part learning-curve and part legitimate concern. To the extent that users encounter these prompts and try them out, we just need to wait for time to pass before the App Store expectation is dampened. To the extent that users and developers truly want App Stores, it's possible in the future. More on that below.
Next, in today's Chrome, there isn't any way other than the prompt for the user to understand that the site they're on is an app. If the user rejects the prompt there isn't much the site can do about it. Yes, there's the "Add To Homescreen" menu item, but it doesn't differentiate between plain-old-websites and PWAs in any visual way (despite using PWA metadata if available...very confusing). As a user, I'd love a visual indicator that let me know if sites I'm on are PWAs that I could keep; this is what "ambient badging" (the next section) is about.
Lastly, as Ada noted, developers aren't in control of the prompting timing. This is intentional. In conversation with developers and users, we came to understand 2 things very clearly:
Web developers do not feel as though they are doing anything wrong -- or worse, feel powerless to prevent their businesses from -- prompting users in ways that create horrible experiences.
The predictable result of this situation is that if a browser allowed users to be prompted to add something to the homescreen whenever the developer wanted, the overall experience of using the web would suffer. This isn't academic: we did this wrong with Geolocation and now we're having to walk it back; through pleading, data, and yes, breaking changes. As a team that cares most about users and a healthy web ecosystem, repeating mistakes like this simply isn't acceptable. The predictable result of designing the API the way Ada and others have suggested would be that we'd have to change it later. That change would likely have been of the form "you can call this API all you want, but the prompt isn't going to show until the user has engaged with your site".
What we went with in the end is simply the same thing, but inverted: by doing all the work to make your thing a Progressive Web App, you've signaled to us that you really do want users to keep this thing to their homescreens. If the timing isn't right, Chrome, Samsung Internet, and Opera let you delay the prompt and show it at a time of your chosing later using onbeforeinstallprompt.
Where the prompt design ended up is exactly where it would have come to rest anyhow; we just short-circuited user pain and spammy experiences.
One final point on prompting: the browser controlling when prompts happen was inevitable, but doing it this way has also allowed us to iterate and experiment. Chrome continues to change the engagement heuristic used to trigger the prompt. In the last year it has fallen from requiring 3 navigations with an hour between 2 of them to only requiring that the user scroll and tap while in a site for a few minutes. All of this is a direct response to developer feedback that they'd like the prompt to trigger more often, which we're balancing with user feedback about when and how often they're prompted. We're also watching the rates at which users accept the prompts. A fall in those rates would signal that we're being too aggressive, but thus far we haven't seen a drop.
The net effect, then, has been that PWAs haven't been introduced to users as a way that they can be spammed or which they (in general) resent. This mirrors how we designed Web Notifications: unlike native apps that frequently take the installation step as carte blanche to spam users with notifications, Web Notifications are always opt-in and easily user-controlled. This sort of careful API design that takes the cumulative experience of users into account is what sets the web apart. Unlike other software ecosystems, the web is not predatory by default and we aim to keep it that way while extending its capabilities further.
But enough about what we've done; what's next? Ambient badging!
Wouldn't it be great if there were a button in the URL bar that appeared whenever you landed on a PWA that you could always tap to save it to your homescreen? A button that showed up in the top-level UI only when on a PWA? Something that didn't require digging through menus and guessing about "is this thing going to work well when launched from the homescreen?" Such a button/indicator would let us do things like say to friends, colleagues, and customers "to get the Example app, go to example.com and tap the Frobulate button".
This sort of badging doesn't require any engagement from the user; it's a non-invasive signal that says "hey, this is something you can keep!".
We're actively working on ambient badging in Chrome for Android, but I'm honestly surprised that no other browser has beat us to the punch. When combined with prompting, ambient badging solves (or I hope it will solve) the inability to "verb" PWAs, to have a common visual and conversational vocabulary around "keeping" PWAs, and dealing more elegantly with discoverability for developers who feel frustrated by the prompt's capriciousness.
App Stores have been part of my thinking around PWAs long before they were called "PWAs". All of the technology that we use for PWAs -- Manifests, Service Workers, and URLs -- are compatible with any store that wants to list them. This, I think, is a major un-tapped area of exploration and it's not exclusionary to ambient badging or engaged-user prompting. It's possible for a browser or platform to implement one, two, or all of these mechanisms in parallel.
Imagine a future version of a desktop OS you use every day. In our ever-more App Store-mediated desktop OSes, it seems natural to go looking for apps to "keep" there. In this sense, App Stores are search engines for "keepable" experiences. PWAs are exactly that: keepable experiences. The meta-data around listing and installation are all available and no separate bundle or package needs to be made. All the app store in question needs to do is to verify that the person listing the app is actually the owner, that the app meets whatever legal guidelines they enforce, and that the site meets the PWA criteria. Most of this is automatable and all of it is possible with the PWA technology we've deployed already. To the extent that changes are necessary to support it, the Manifest spec is explicitly designed to be extensible.
App Stores are another area where I'm surprised that we haven't seen more non-Chrome innovation. Can't wait to see what happens there next. PWAs are great fit for these "keepable experience" search engines.
If PWAs are by-design App Store-compatible -- assuming those stores want to allow them to be listed and "kept" and aren't just pursuing proprietary visions where businesses pay exhorbitantly to re-develop for each platform and form-factor -- then Search engines are the proto-App Store.
It's possible to imagine Bing.com supporting specially highlighted & badged links that can be opened stand-alone by default if the resulting URL is a PWA...say a separate "open standalone" link next to a result. It's also possible to imagine separate "keep and visit" buttons in search results for URLs that are part of PWAs. Again, this future has been part of my thinking around distribution for PWAs for a long, long time, but it has only relatively recently become possible for crawlers to detect and enforce the quality bar that PWAs set.
Obviously, I have no inside information about what Bing's engineers think the future should look like, but if it seems natural for search engines to list Native Apps (which they do today), then this also seems mighty reasonable.
What's important about PWAs, then, is that they are OG "streamable apps". Most users won't install most PWAs most of the time, and that's fine. Hoping for more is how the tech industry found itself over-funding a gold rush only to reap the predictable consequences. The notion that native apps are "better" has largely been a self-reenforcing mantra borne of a Silicon Valley monoculture wherein the needs of billions are simply presumed (without investigation) to be the same as the behaviors of VC's kids, nephews/nieces, and close associates.
It's maddening. It's idiotic. But it's also why the web has a shot. Bubbles burst and the web will finally be ready to pick up the slack when this one does.
Most "opens" of PWAs happen in tabs through normal navigation. This has multiple causes, including an inability (which we'll resolve at some point) for Chrome to be able to open navigations to PWAs from external sources in non-browser mode.
Very few sites were using display: "browser". This means that the change Jeremy objected to affects a minuscule number of sites (today). Now, obviously, Jeremy could go and evangelize all PWA developers to use display: "browser", but that sort of seems misguided because...
It doesn't solve the problem of URL access or Sharing for sites that chose a different mode (e.g. fullscreen, standalone, or minimal-ui).
That last point is the high-order bit for me. Like Jeremy, I'm agitated over the lack of access to URLs for PWAs launched in a more immersive mode. That seems to be the thing to be frustrated about if you care about URLs and sharing and it's my concern too -- so much so that our team prioritized fixing it this quarter. New UI and gestures are hard to get right which is why I'm excited that Owen and Rebecca have been looking into how to make URLs accessible to PWA users no matter what display mode they're in. We'll have more to show on this front soon.
We're going to do something about this imminently because web developers who are building PWAs tend to forget about sharing. It's been painful in our audits of partner apps to have to remind them to "build a share button" and then make sure it's available on-screen in the right modes. It sucks to implement and it's harder to use than a ubiquitous UI contract. At the same time, successful PWA developers are striving for UI consistency with the native platform their apps run on. They want their Web cake and the want to eat it like an App. The onus, then, is clearly on the browser to bring URL access back in ways that developers can't defeat and can't forget.
Which brings us to a final point that seems to have been lost: browsers can fix the real issue -- sharing of PWAs and access to URLs -- without anyone changing anything about their apps, and can do it out-of-band. Obviously, this is only true for browsers that support PWAs and have fast update cycles which, today, is all PWA-supporting browsers; namely Chrome, Opera, and Samsung Internet. The folks who work on these browsers -- including myself -- care as much as Jeremy does about the health and future of the web. I'm grateful to him for highlighting this issue and hope we can work together in the future to figure out ways to keep the best bits of the web healthy as PWAs become a common way to get back to sites users love.
A lot of smart folks keep asking me why AppCache isn't a good enough solution for "offline" and why it was necessary to invent Service Workers. It's a great question!
Motivated by the regrettably uneven browser support landscape for Service Workers, there's a real incentive to "just make something work offline" on iOS or old-IE. This phrasing obscures the primary experience difference between native apps and web content: native apps always "boot" when you tap on them. The legacy web, however, can take as long as the TCP timeout (2 minutes in many devices) to end in failure. That's a looooong time to be looking at a white screen.
But doesn't AppCache let you cache documents you might want offline? Sort of. Kinda. Ish. Turns out this only works in trivial cases. The issue is that the AppCache design only allows you to do "routing" using the FALLBACK section, and to trigger the FALLBACK URL (which can boot up, inspect it's environment, and do something custom) the request needs to have actually failed. To handle the general case -- a site with an unbounded set of URLs -- that means users are waiting on a flaky, slow network for minutes (if they're patient) before the the router page starts, which might then forward them on to content or a custom offline experience.
"But wait!", you say, "doesn't AppCache also allow you to put documents in the cache directly, bypassing all of that?". Yes, it does, but because of AppCache's atomic update system and practical limits to storage space, this means that the set of URLs in this list needs to be low and change infrequently. You see this play out, for example, in the AppCache manifests that major Google services like Google Docs generate. These services wind up with major complexity related to creating manifests on a per-user basis and managing the entries in them. Those entries are carefully curated from amongst the entire set of possible URLs to ensure high performance for the entries users are likely to visit offline, but this still leaves everything else at the mercy of network flakiness.
It's hard to stress enough how much better reliable performance is. Think of it this way: the first load of a native app sucks. It's gated by an app store and a huge download, but once you get to a point where the app is installed, that up-front cost is amortized across all app starts and none of those starts have a variable delay. Each application start is as fast as the last, no variance. What native apps deliver is reliable performance.
Remy Sharp blogged about the experience and expectation differences that we've worked hard to bake into Progressive Web Apps. Reliable performance is the most important of these and the reason Progressive Web Apps require Service Workers. It isn't that "offline" support doesn't matter -- it does -- but apps that work well offline are a subset of things that are apps, experiences you can trust to start any time, anywhere, on any connection.
I'll be speaking more about this at Google I/O in a few weeks, and I'm hugely excited about the ways that the web is going to get better this year; starting with experiences that always work.