Install serviceworker-rails for Rails 5 + Webpacker
diff --git a/Gemfile b/Gemfile
index 4983412..454bd32 100644
--- a/Gemfile
+++ b/Gemfile
@@ -11,6 +11,10 @@ gem 'pg', '>= 0.18', '< 2.0'
gem 'puma', '~> 3.11'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '>= 4.0.x'
+
+# Turn your Rails app into a Progressive Web App. https://github.com/rossta/serviceworker-rails
+gem 'serviceworker-rails', github: 'rossta/serviceworker-rails'
+
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use ActiveModel has_secure_password
diff --git a/Gemfile.lock b/Gemfile.lock
index 9414509..6be13c9 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,3 +1,10 @@
+GIT
+ remote: https://github.com/rossta/serviceworker-rails.git
+ revision: 757db5354c9e47a144397c4655f3d1cab6046bc0
+ specs:
+ serviceworker-rails (0.5.5)
+ railties (>= 3.1)
+
GEM
remote: https://rubygems.org/
specs:
@@ -185,6 +192,7 @@ DEPENDENCIES
puma (~> 3.11)
rails (~> 5.2.1)
selenium-webdriver
+ serviceworker-rails!
spring
spring-watcher-listen (~> 2.0.0)
tzinfo-data
diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js
index 54b106e..76062e6 100644
--- a/app/javascript/packs/application.js
+++ b/app/javascript/packs/application.js
@@ -7,4 +7,4 @@
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
-console.log('Hello World from Webpacker')
+import 'serviceworker-companion';
diff --git a/app/javascript/packs/serviceworker.js b/app/javascript/packs/serviceworker.js
new file mode 100644
index 0000000..abf2e9f
--- /dev/null
+++ b/app/javascript/packs/serviceworker.js
@@ -0,0 +1,57 @@
+console.log('[Service Worker] Hello world!');
+
+var CACHE_NAME = 'v1-cached-assets';
+
+function onInstall(event) {
+ event.waitUntil(
+ caches.open(CACHE_NAME).then(function prefill(cache) {
+ return cache.addAll([
+ '/offline.html'
+ ]);
+ })
+ );
+}
+
+function onActivate(event) {
+ console.log('[Serviceworker]', "Activating!", event);
+ event.waitUntil(
+ caches.keys().then(function (cacheNames) {
+ return Promise.all(
+ cacheNames.filter(function (cacheName) {
+ // Return true if you want to remove this cache,
+ // but remember that caches are shared across
+ // the whole origin
+ return cacheName.indexOf('v1') !== 0;
+ }).map(function (cacheName) {
+ return caches.delete(cacheName);
+ })
+ );
+ })
+ );
+}
+
+self.addEventListener('install', onInstall)
+self.addEventListener('activate', onActivate)
+
+
+function onFetch(event) {
+ // Fetch from network, fallback to cached content, then offline.html for same-origin GET requests
+ var request = event.request;
+
+ if (!request.url.match(/localhost/)) {
+ return;
+ }
+ if (request.method !== 'GET') {
+ return;
+ }
+
+ event.respondWith(
+ fetch(request).catch(function fallback() {
+ return caches.match('/offline.html')
+ })
+ );
+
+ // See https://jakearchibald.com/2014/offline-cookbook/#on-network-response for more examples
+}
+
+self.addEventListener('fetch', onFetch);
diff --git a/app/javascript/serviceworker-companion.js b/app/javascript/serviceworker-companion.js
new file mode 100644
index 0000000..62f8b9e
--- /dev/null
+++ b/app/javascript/serviceworker-companion.js
@@ -0,0 +1,6 @@
+if ('serviceWorker' in navigator) {
+ // Use the window load event to keep the page load performant
+ window.addEventListener('load', () => {
+ navigator.serviceWorker.register('/serviceworker.js');
+ });
+}
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 6e7310e..1ce8ada 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -6,6 +6,7 @@
<%= csp_meta_tag %>
<%= stylesheet_pack_tag 'hello_vue', media: 'all' %>
+ <%= javascript_pack_tag 'application' %>
<%= javascript_pack_tag 'hello_vue' %>
</head>
diff --git a/config/application.rb b/config/application.rb
index 418d35e..9b8dbf4 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -10,7 +10,7 @@ require "action_controller/railtie"
# require "action_mailer/railtie"
require "action_view/railtie"
# require "action_cable/engine"
-# require "sprockets/railtie"
+require "sprockets/railtie"
require "rails/test_unit/railtie"
# Require the gems listed in Gemfile, including any gems
diff --git a/config/initializers/serviceworker.rb b/config/initializers/serviceworker.rb
new file mode 100644
index 0000000..a1b18e7
--- /dev/null
+++ b/config/initializers/serviceworker.rb
@@ -0,0 +1,25 @@
+Rails.application.configure do
+ config.serviceworker.routes.draw do
+ # map to assets implicitly
+ match '/serviceworker.js', pack: 'serviceworker.js'
+
+ # Examples
+ #
+ # map to a named asset explicitly
+ # match "/proxied-serviceworker.js" => "nested/asset/serviceworker.js"
+ # match "/nested/serviceworker.js" => "another/serviceworker.js"
+ #
+ # capture named path segments and interpolate to asset name
+ # match "/captures/*segments/serviceworker.js" => "%{segments}/serviceworker.js"
+ #
+ # capture named parameter and interpolate to asset name
+ # match "/parameter/:id/serviceworker.js" => "project/%{id}/serviceworker.js"
+ #
+ # insert custom headers
+ # match "/header-serviceworker.js" => "another/serviceworker.js",
+ # headers: { "X-Resource-Header" => "A resource" }
+ #
+ # anonymous glob exposes `paths` variable for interpolation
+ # match "/*/serviceworker.js" => "%{paths}/serviceworker.js"
+ end
+end
diff --git a/public/offline.html b/public/offline.html
new file mode 100644
index 0000000..4734435
--- /dev/null
+++ b/public/offline.html
@@ -0,0 +1 @@
+<h1>Offline!</h1>