Getting started with Isolated Web Apps

Enable Isolated Web App developer mode

Task 1

30 minutes

Isolated Web Apps, even when being developed locally, need to run in a near-production environment to gain access to the high-trust APIs available to them. To do this, you need to enable the Isolated Web App Dev Mode:

  • Go to chrome://flags#enable-isolated-web-app-dev-mode and enable the dev mode flag
  • Go to chrome://flags/#enable-isolated-web-apps to and enable Isolated Web Apps flag if you're on a non-ChromeOS device

Once enabled, and Chrome’s restarted, you go to chrome://web-app-internals, the Web App Internals page. This page shows you what web apps, including Isolated Web Apps and Progressive Web Apps, you have installed, with details for each. You’ll know everything is enabled correctly if you have the Isolated Web Apps section at the top of the page.

A screenshot of the Web App Internals page, with the Isolated Web App section available. There are three sections total, the top section has two buttons, "download" and "copy to clipboard" which are directed at the contents of the third section, an an array of objects describing what apps you have installed. The second section is titled Isolated Web Apps and has a form field labeled "Install IWA via Dev Mode Proxy" with a URL input and an install button, a field labeled "Install IWA from Signed Web Bundle" with a file select button, a subsection called IWA Updates with a button titled "Discover updates of policy-installed IWAs now", and a final subsection titled "Dev Mode App Updates" that is empty until an IWA is installed.

The Isolated Web Apps developer mode has two ways to install your IWA for testing: either through a developer mode proxy, or by uploading a signed web bundle. The proxy will take any URL that meets minimum IWA installation requirements (has a valid web application manifest at /.well-known/manifest.webmanifest that includes a name, at least one valid icon, and a version field set to a SEMVER string) and will install an Isolated Web App to your system that wraps that site without needing to bundle its assets (all other requirements for an IWA’s isolated runtime still apply). Uploading a signed bundle will go through the full install process and only load assets from that bundle.

You can also update installed IWAs. When using the proxy, you only need to use the update process when making changes to the web app manifest. This means that, if your development server supports hot module replacement (HMR), you can configure it to work with your installed development IWA! For bundled IWAs, any change you make will require you running the update process. Remember to bump your version number whenever you run the update process.

You uninstall development IWAs just like you would any app on your computer.

Configuring hot module replacement for the IWA development proxy

Hot module replacement (HMR) is a feature of many tools and development servers (like Webpack and Vite) that allow real-time updates to a running application without requiring a full site reload. It can speed up development time by only updating what’s changed and doing it near instantly, as if you had made the changes directly in-browser, and lets you retain state when making changes. HMR can work with IWAs installed through the proxy, but it requires some extra configuration on your part.

HRM is usually powered by WebSockets and often dynamically determines what hostname and protocol to use based on the client’s protocol and hostname. This, unfortunately, doesn’t work for Isolated Web Apps. IWAs installed through the proxy get an isolated-app:// protocol with a dynamically generated hostname (created at install time) to mimic the public key that’s used as an identifier when installed from a bundle. Because the proxy doesn’t also proxy the WebSocket, you’ll likely need to manually configure your tools to connect to the WebSocket correctly. The key to doing this is to mimic the HMR URL that would be used if you were in a tab. This means:

  • It uses the WebSocket protocol ws
  • It’s served from the localhost host
  • It’s running on the same port as your development server

For WebPack, you need to set both the devServer.port to ensure the server is running on a specific port and the devServer.client.webSocketURL config to set the protocol, hostname, and port, as well as letting all hosts connect to the dev server:

Webpack config
devServer: {
 port: 4321,
 allowedHosts: 'all',
 client: {
   webSocketURL: {
     protocol: 'ws',
     hostname: 'localhost',
     port: 4321,
   }
 }
}

For Vite, you similarly need to set the server.port to ensure the server is running on a specific port and the server.hmr config to set the protocol, hostname, and port:

Vite config
server: {
 port: 4321,
 hmr: {
   protocol: 'ws',
   host: 'localhost',
   clientPort: 4321,
 }
}

Your turn