pwa 0.1.4

Progressive Web App (PWA) for Dart

Progressive web apps (PWA) are a hybrid of regular web pages (or websites) and a mobile application. This new application model attempts to combine features offered by most modern browsers with the benefits of mobile experience.

Warning: the API is experimental, and subject to change.


PWA is using ServiceWorkers:

Learn more about PWAs:

Tutorial and Examples

Getting started

  • Getting started: pwa_defaults

    • Shows you how to use the pwa package and what it does.
    • Enables offline asset caching for you web app out-of-the-box.
  • Additional offline urls: additional_offline_urls

    • Show you how to create the entry point for customization.
    • Gives you the ability to add additional URLs for the offline cache.

Customize caching

  • Custom routes: custom_routes
    • Familiarize yourself with caching and routes.
    • Customize cache behavior for different parts of your app.

Push notification

  • Push notification: push_notification
    • Check and/or request Push permission.
    • Trigger and handle push event, show notification.

Planned features

  • Typed Window <-> Worker communication, both Streams and request-reply patterns, something like:

    typedef Future<S> AsyncFunction<R, S>(R request);
    typedef S WireAdapter<R, S>(R input);
    abstract class MessageHub {
      AsyncFunction<R, S> getFunction<R, S>(String type,
          {WireAdapter<R, dynamic> encoder, WireAdapter<dynamic, S> decoder});
      void setHandler<R, S>(String type, AsyncFunction<R, S> handler,
          {WireAdapter<dynamic, R> decoder, WireAdapter<S, dynamic> encoder});
      Sink<T> getSink<T>(String type, {WireAdapter<T, dynamic> encoder});
      Stream<T> getStream<T>(String type, {WireAdapter<dynamic, T> decoder});
  • Push Notification

    • notification for the client app
    • one-method registration and/or status request



  • Expose clientKeys in PushPermission.


  • Workaround for a bug in Chrome: ServiceWorkerContainer.ready may not complete in certain cases (for no apparent reason). Added a timeout of two seconds and return the registered SW instance.

  • Added higher-level API helpers for checking Push permission and handling push events.


  • Filter offline URLs:
    • dart2js debug outputs (
    • package:test and package:package_resolver assets


  • Generating lastModified timestamp (in String) for offline URLs.
  • Encouraging (but not yet enforcing) to use a version String in
  • The generated pwa.dart uses offline.lastModified as the version.


Breaking changes:

  • Remove deprecated methods and classes (see changes in version 0.0.5).

  • Changed the initialization of the Service Worker:

    • pwa.g.dart -> pwa.dart (source code generation is one-time only)
    • Client unregisters old version (ANY ServiceWorker ending with /pwa.g.dart.js)
  • Worker.onInstall and Worker.onActicate became fields (instead of being methods).


API refactoring:

  • Remove Pwa class name prefix (not immediately breaking, added deprecated notes)

    • PwaClient -> Client
    • PwaWorker -> Worker
    • PwaCacheMixin -> FetchStrategy
  • Renamed ambiguous items related to the Fetch API (not immediately breaking, added deprecated notes)

    • Handler -> RequestHandler
    • Matcher -> RequestMatcher
    • Router -> FetchRouter
    • defaultFetchHandler -> defaultRequestHandler
    • noCacheNetworkFetch -> noCacheNetworkRequestHandler
  • Renamed DynamicCache's noNetworkCaching -> skipDiskCache (not immediately breaking, added deprecated notes).

  • Updated methods in FetchRouter (not immediately breaking, added deprecated notes)

    • add -> registerMatcher
    • new method: registerUrl (will make urlPrefixMatcher internal)
    • get -> registerGetUrl
    • post -> registerPostUrl


  • Fix path separators on Windows.
  • Updated examples:
    • Added pwa_defaults.
    • Moved example into examples/custom_routes.
  • Execute pub build when the project has no build/web directory yet.


Breaking changes:

  • (API) BlockCache and DynamicCache don't expose their initialization parameters. This is a minor change, it is unlikely to affect anybody.

  • (behavior) BlockCache and DynamicCache use path-specific cache prefixes, in order to prevent collision between apps that are installed on the same domain.

    This fixes unintended cache collisions, but also breaks if you were building on sharing the caches between apps. In this case, use the new prefix optional argument when instantiating caches.

    If you have used only a single application in the root of the domain, you are not affected by this change.


  • Fix default codegen.
  • Call skipWaiting() by default (can be disabled through flag).
  • The generated offline URLs and the SW registration is changed to relative URLS, we can put the application in any directory.
  • DynamicCache evicts older entries first (previously it was random).
  • DynamicCache doesn't evicts old entries on initialization, which enables offline-aware caches to outlive the set expiration until the next successful network event.
  • Support for caching common web fonts.


Experimental release, looking for feedback.

1. Depend on it

Add this to your package's pubspec.yaml file:

  pwa: "^0.1.4"

2. Install it

You can install packages from the command line:

$ pub get

Alternatively, your editor might support pub. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:pwa/client.dart';
import 'package:pwa/worker.dart';


Progressive Web App library


Email Istvan Soos



Source code (hyperlinked)