ampproject / amp-sw

A drop in service worker library to help your AMP pages gain network resiliency in 1 line

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Facilitate building with workbox already available as external

westonruter opened this issue · comments

In the AMP plugin for WordPress, work is underway (ampproject/amp-wp#1261) to incorporate features from AMP by Example's serviceworkerJs.js. However, there are key features in amp-sw.js which aren't implemented yet. Ideally the AMP plugin would be able to import amp-sw.js cleanly to take incorporate its functionality into the WordPress plugin. This, however, is not as simple as just adding the one-line importScripts call.

The service worker in WordPress is generated by the PWA feature plugin which is intended to be merged into WordPress core. This includes a copy of Workbox in itself which is aliased as wp.serviceWorker, with the intention that WordPress wouldn't be tied to Workbox forever.

The service worker in WordPress is designed to be extensible by themes and plugins to each include their own functionality. There is a PHP abstraction that they can use which translates PHP API calls into the equivalent Workbox calls (under the wp.serviceWorker namespace), allowing WordPress developers to continue using the preferred server-side language and WordPress then constructs the service worker JavaScript dynamically. In short, WordPress needs the amp-sw.js to be living alongside the other logic introduced by other players on a given WordPress install.

Given that WordPress already includes a copy of Workbox, it would be ideal if the AMP plugin could similarly bundle a custom build of amp-sw.js which does not have Workbox modules bundled inside of it. In other words, if the workbox modules were externalized as wp.serviceWorker:

diff --git a/webpack.config.js b/webpack.config.js
index 397f22d..a8438a5 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -49,6 +49,13 @@ module.exports = {
     chunkFilename: '[name].js',
     publicPath,
   },
+  externals: {
+    workbox: [ 'wp', 'serviceWorker' ],
+    'workbox-strategies': [ 'wp', 'serviceWorker', 'strategies' ],
+    'workbox-routing': [ 'wp', 'serviceWorker', 'routing' ],
+    'workbox-navigation-preload': [ 'wp', 'serviceWorker', 'navigationPreload' ],
+    'workbox-cache-expiration': [ 'wp', 'serviceWorker', 'expiration' ],
+  },
   target: "webworker",
   mode: "production",
   module: {

Given the above, the AMP plugin for WordPress would merely need to include something like the following PHP code to incorporate amp-sw.js into the service worker served by WordPress:

add_action( 'wp_front_service_worker', function( WP_Service_Worker_Scripts $service_workers ) {
	$service_workers->register( 'amp-sw', function() {
		$script  = file_get_contents( AMP__DIR__ . '/assets/js/amp-sw.js' );
		$script .= sprintf( 'AMP_SW.init( %s );', wp_json_encode( AMP_Service_Worker::get_options() ) );
		return $script;
	} );
} );

Also, the PWA plugin in WordPress already enables navigation preload, so we could exclude that functionality entirely from a custom WordPress build of amp-sw.js. Likewise, the PWA WordPress plugin also provides configuration for whether to clientsClaim and skipWaiting.

So, what could be done to facilitate amp-sw.js into WordPress in this way?

I suppose adding amp-wp as a dev dependency to the AMP WordPress plugin would be where to start, and then have a custom Webpack config along with a modified entry point that tweaks which modules are loaded.

The AMP ServiceWorker so far has operated with the expressed goal of not exposing Workbox (as it's not certain it will continue to use it). Instead the goal has been to express a stable API with a transparent to the end developer implementation internally.

Integration with WordPress might not be straightforward given the goals and approach described.