Shipping PWAs as Chrome Extensions
Tags: pwa, chrome
Published: 2018-08-18 11:34:42

---
title: Shipping PWAs as Chrome Extensions
published: true
description: Emojityper 🤣⌨️ is a PWA that works offline—but you can also access it as a Chrome Extension in your toolbar.
tags: pwa, chrome
cover_image: https://thepracticaldev.s3.amazonaws.com/i/82yxcuizy1swqzqe1oyn.png
---

Progressive Web Apps, or PWAs, are basically a type of website that works offline and may include native app-like features. But realistically, the PWA [moniker](https://google.com/search?q=define%3Amoniker) is something you tell your boss, your investor, whoever, so they can conceptualize this web thing that you're building.

So you've built a PWA, created your service worker, and followed [all](https://developers.google.com/web/progressive-web-apps/) [the guides](https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp/). In my case, that is [Emojityper](https://emojityper.com): a simple PWA where you can enter words, and receive emoji. This is perfect for desktop and entering emoji in editors that don't support them. ⌨️🔜🤣

![Emojityper Chrome Extension showing its browser action](https://thepracticaldev.s3.amazonaws.com/i/mgv1tc3rt3bgciuatgrm.png)

But once you've built this great experience, you're not limited to distributing it only on the 'web'. In this post, I'm going to detail how I shipped [Emojityper](https://emojityper.com) as a [Chrome extension](https://chrome.google.com/webstore/detail/emojityper/cbkooiohnnlhpelnllknmenlhiglnkap), accessible via a [browser action](https://developer.chrome.com/extensions/browserAction).

<hr />

**Creating an extension for your PWA is incredibly simple.** Why? Because if your PWA already works offline, you can leverage the fact that Chrome is already caching it for your users. We're literally just building a small embedder that includes your site in an `iframe`. Let's start! 🏁

## Extension Files

There's basically two files that make up our Chrome extension. First, the `manifest.json` file, describing some metadata:

```json
{
  "name": "Emojityper",
  "version": "0.2",
  "description": "Type emoji on your keyboard!",
  "browser_action": {
    "default_popup": "embedder.html",
    "default_title": "Emojityper",
    "default_icon": {"128": "i128.png", "32": "i32.png", "16": "i16.png"}
  },
  "icons": {"128": "i128.png", "32": "i32.png", "16": "i16.png"}
  "manifest_version": 2
}
```

This manifest could also request [additional permissions](https://developer.chrome.com/extensions/declare_permissions) for features that are available to Chrome extensions. However, as we're just embedding a PWA that already takes advantage of the web platform's features—you should try to avoid it.

And next, the `embedder.html` file, which embeds your PWA in an `iframe`:

```html
<!DOCTYPE html>
<html>
<head>
<style>
  body {
    background: #2c3e50;
    margin: 0;
    width: 380px;
    height: 200px;
  }
  iframe {
    width: 100%;
    height: 100%;
    border: 0;
  }
</style>
</head>
<body>
  <iframe id="iframe" src="https://emojityper.com/?utm_source=chrome_ext"></iframe>
</body>
</html>
```

Save these two files 💾⬇️📂 in a single folder (along with some icons—`i16.png`, `i32.png`, `i128.png`, or maybe fewer if you can get away with it), then head to `chrome://extensions`, enable Developer mode, and select "load unpacked extension".

![Extension development](https://thepracticaldev.s3.amazonaws.com/i/sduvftzakknj1odyjuxt.png)

Great! You'll now see the Emojityper app appear in your extension bar and clicking on it will bring up the display we saw earlier.

<hr />

# Challenges

Your PWA might just start working well. You've embedded into a handy popup that's hopefully helpful for your users. But there's two nuances.

## Responsive Design

Our extension lives in an area 380 pixels wide by 200 pixels high. You can make this larger, of course, but the point is to provide a conveniently small UI. And while browser tabs can also be shrunk to this size—on my Mac, the smallest Chrome window I can make is 400 wide by 159 high—your users might expect to use your PWA [on their desktop](https://developers.google.com/web/updates/2018/05/dpwa) as say, a small music controller or other 'widget'. 🎶🔁

This all basically means that you might have to add a "micro" mode to your responsive design. Emojityper went from cluttered to simple by adding CSS for heights of 400px or less:

![Clutter to simple](https://thepracticaldev.s3.amazonaws.com/i/wvbh4g2xgwg6jcqt3ypo.png)

## Extension Perks

The PWA we've embedded just works, because you're leveraging the web platform. But there'll always be things that an extension can do that your PWA can not.

In Emojityper's case, hitting the "copy" button should actually close the extension window. This is implemented by having the PWA look for its 'parent': the container/embedding page, and letting the parent know when copy was done. Inside Emojityper, I do something like this:

```js
function notifyParentCopy() {
  // notify parent (for ext)
  if (window.parent) {
    window.parent.postMessage('copy', '*');
  }
}
```

And in the extension, I add an included JS file which listens for messages and takes action:

```js
window.addEventListener('message', (ev) => {
  switch (ev.data) {
  case 'copy':
    window.close();
    break;
  default:
    console.warn('got unhandled message', ev.data);
  }
});
```

(Because our extension isn't actually hosted on a domain, it can just communicate with the embedded `iframe` without any security challenges.)

Is it worth detecting 'extension mode' and providing additional features? That's up to you. This article is mostly about bringing your PWA to where your users are, so I'd argue that only a bare minimum of additional features might make sense (in the same way that you probably don't need to request any permissions).

<hr />

Thanks for reading! I hope you've learned a bit more about [Emojityper](https://emojityper.com) and its [Chrome extension](https://chrome.google.com/webstore/detail/emojityper/cbkooiohnnlhpelnllknmenlhiglnkap). 😂

You could take a similar approach to include your PWA inside an Android, iOS or desktop native app via a web view. Your PWA can extend its distribution, and go where your users want to be. 🔜👥👏👩‍💻👨‍💻