Building PWAs with Web Components!

Looking to build a Progressive Web App but not sure where to start?
January 11, 2021
| Software Engineer
An image of 3 people working together to build a Progressive Web App!

There are MANY ways to build great Progressive Web Apps but today I wanted to share an approach that we have been exploring, building PWAs with Web Components based solutions! Specifically, we will be discussing the following technology stack:

A quick note before we dive into the content: Our goal with sharing this with the community is not to say this is the only way to build web apps, or that it is even the absolute best way to build web apps, instead we wanted to share what works well for us in the hopes that it can help drive your teamΓÇÖs decisions around what works well for you and your application.

Setting our Goals

When you are going to build a new app (of any kind) there are a series of decisions that must be made up front. These decisions normally involve picking a technology stack based on some set of goals for the project. With PWAs this becomes even more important as there are many frameworks, libraries, build tools and more to choose from and these choices can have large impacts on your PWA as you develop it. For example, if loading performance is a key metric for your application then the framework that you choose to build the application in at the beginning can have a significant impact on loading performance farther down the road. For the PWABuilder team our key goals look something like the below:

Based on the above we have found that browser native, Web Components based solutions combined with tooling that is focused on simplicity and sticking to web standards gives us the easiest path to meeting these goals. Let’s dive into the details of this approach!

Web Components? lit-element?

Web Components! How do I build a whole app with them? Don’t I need something like React or Angular to build the app? Let’s answer those questions and more!

What are Web Components?

First, let’s touch on what Web Components are. Web Components are a collection of Web APIs that allow you to build components. You can think of this as the same as components you build with something like React or Angular, but there are some key differences with Web Components. They are currently supported in all browsers besides Internet Explorer.

browser support table for web components. All modern browsers are supported, including Safari

What is lit-element?

Lit-element is a library / framework that makes it easy to build Web Components. Lit-element gives us a way to write code that feels very familiar to popular frameworks like React but with Web Components. It also includes a tiny runtime that provides things such as performant asynchronous rendering. Also, lit-element is now only one of many Web Components based frameworks / libraries that are available. We also recommend checking out fast-element and Stencil

Why Web Components?

- Performance

First, components built with either React or Angular are not native components understood by browsers. Because of this, you need to ship a large runtime (the core of both React and Angular) of some sort that can run these components in the browser. Note that this is a basic explanation of how these frameworks work, there are of course many details in the actual implementations, but these details are not truly relevant to our discussion today. This runtime cost is a huge part of the loading performance issues that apps built with these frameworks commonly have.

With Web Components based frameworks you avoid this large runtime cost as the browser natively understands Web Components, but without sacrificing developer experience. This enables frameworks to still ship features such as performant async rendering but without the code associated with just running the components. For example, let’s use BundlePhobia cost of adding a npm package to evaluate the cost of React, Angular and lit-element:

React:

React is 121.1kb minified and 39.4kb minified and compressed with GZIP

Angular:

Angular is 289.9kb minified and 88.7kb minified and compressed with GZIP

and then lit-element, a Web Components based solution:

lit-element is 23.2kb minified and 7.4kb minified and compressed with GZIP

Lit-element is awesome here as the developer experience is extremely similar to React but with a much smaller bundle size!

Maintainability / Stability

Web Components, by their nature of being Web Standards, are inherently going to be more stable than any custom code. For example, the Geolocation API is a web standard and because of this, once it was implemented in a browser it has consistently worked since and we can count on it continuing to work far into the future because of the webs guarantee on not breaking existing websites. There are of course drawbacks with this approach, such as it taking longer for Web Standards to be implemented compared to the React team implementing a new feature in React. However, this is a tradeoff that we feel is fair in return for a good guarantee on long term stability.

Styling with Web Components

Continuing with our Web Standards first approach, modern CSS now has built in APIs / features in browsers that give us all the features we normally use a CSS pre-processor such as SASS for:

Variables CSS now has CSS variables! CSS variables work great with Web Components and work extremely similar to variables in SASS.

Style Encapsulation Shadow DOM is part of the Web Components spec and helps fix the classic CSS cascade issue. Shadow DOM enables you to encapsulate your styles “inside” of your component, ensuring that CSS elsewhere in your app does not accidentally override CSS in your component. However, using both CSS Variables and the Shadow Parts API we can enable specific pieces of our components to be style-able from outside of the component. This is helpful when you want a component to have certain styles customizable but still have default styles too.

Build Tools

Luckily, by basing the rest of our tech stack on Web Standards it also makes setting up our build tools easy!

Bundler

For our bundling we use Rollup which is described on the Rollup Website as:

Rollup is a module bundler for JavaScript which compiles small pieces of code into something larger and more complex, such as a library or application. It uses the new standardized format for code modules included in the ES6 revision of JavaScript, instead of previous idiosyncratic solutions such as CommonJS and AMD. ES modules let you freely and seamlessly combine the most useful individual functions from your favorite libraries.

As you can guess, lit-element also uses standard built-in ES modules and because of this it works seamlessly with Rollup! Rollup also runs other tasks that are important for our builds:

Workbox (Service Worker)

We use Workbox which is a tool that makes working with Service Workers easy! Workbox enables you to build fully customized offline experiences for your app while also simplifying many of the complicated parts of Service Workers, such as pre-caching. We also use the Workbox Rollup plugin which makes it super easy to do pre-caching of our assets which not only is a huge part of the offline experience, but also ensures that our PWAs load even faster after the user has loaded the app at least once! Better performance AND an offline experience with only a few lines of code is always awesome!

Project Fugu

Native APIs! This is an area where PWAs (and Web Apps in general) have lacked in the past and because of this we saw the rise of awesome tools such as Cordova Ionic Native Electron and more! However, with the rise of Project Fugu web standard PWAs, with no native toolkit of any kind installed and using plain JavaScript APIs, can do almost all the same things a Native app can! For example, in the latest stable Edge and Chrome PWAs can:

And this is just a tiny bit of what’s possible! For the full list check the Project Fugu status page! New capabilities status (web.dev)

Get started building a PWA with this tech stack!

If your goals are similar to ours and you want to give this tech stack a try you should check out the PWABuilder pwa-starter This starter includes everything we discussed above and has everything set to what we think are good defaults. Also, if you are looking for a tutorial feel free to check out this video for a walk through on using the starter.

Alright, that is how we are building PWAs fully with web components! Remember to check out the starter above if this tech stack interests you and please feel free to add any feedback as an issue on the repo. And, once your PWA is ready to go donΓÇÖt forget to come back to PWABuilder to get your PWA in the app stores! The PWABuilder team is going to be rebuilding PWABuilder with this tech stack for 2021, and we are very excited to show you the results when we are done! The web and the amazing community around it have us excited to see where PWAs go this year!

Share this article on your social media!

Author Profile

profile picture

Justin Willis @Justinwillis96

When i'm not developing PWAs you can find me hiking, gaming or playing with my pets!