I am using the serviceworker-rails gem to make my eCommerce application a progressive web app. Here is a gem file snippet from the project;
# progressive web application gem
gem 'serviceworker-rails'
# eCommerce gems
gem 'solidus'
gem 'solidus_auth_devise'
#base gems
gem 'rails', '~> 5.2.0'
ruby '2.5.1'
the serviceworker-rails gem in turn generates the manifest files needed to make the app a progressive web application;
app/assets/javascripts/serviceworker.js.erb
var CACHE_VERSION = 'v1';
var CACHE_NAME = CACHE_VERSION + ':sw-cache-';
function onInstall(event) {
console.log('[Serviceworker]', "Installing!", event);
event.waitUntil(
caches.open(CACHE_NAME).then(function prefill(cache) {
return cache.addAll([
// make sure serviceworker.js is not required by application.js
// if you want to reference application.js from here
'<%#= asset_path "application.js" %>',
'<%= asset_path "application.css" %>',
'/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(CACHE_VERSION) !== 0;
}).map(function(cacheName) {
return caches.delete(cacheName);
})
);
})
);
}
// Borrowed from https://github.com/TalAter/UpUp
function onFetch(event) {
event.respondWith(
// try to return untouched request from network first
fetch(event.request).catch(function() {
// if it fails, try to return request from the cache
return caches.match(event.request).then(function(response) {
if (response) {
return response;
}
// if not found in cache, return default offline content for navigate requests
if (event.request.mode === 'navigate' ||
(event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html'))) {
console.log('[Serviceworker]', "Fetching offline content", event);
return caches.match('/offline.html');
}
})
})
);
}
self.addEventListener('install', onInstall);
self.addEventListener('activate', onActivate);
self.addEventListener('fetch', onFetch);
app/assets/javascripts/serviceworker-companion.js
if (navigator.serviceWorker) {
navigator.serviceWorker.register('/serviceworker.js', { scope: './' })
.then(function(reg) {
console.log('[Companion]', 'Service worker registered!');
});
}
The application does not raise up any errors; just that I happen to notice that the service worker is not being registered. Here is the manifest in use;
app/assets/javascripts/manifest.json.erb
{
"name": "My Progressive Rails App",
"short_name": "Progressive",
"start_url": "/"
}
...and finally;
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Istore</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
<link rel="manifest" href="/manifest.json" />
<meta name="apple-mobile-web-app-capable" content="yes">
</head>
<body>
<%= yield %>
</body>
</html>
To be fair; I have used this set up before and it worked good. Something breaks when I use it with solidus_gem. So far; my efforts to debug the issue has only zeroed me in on a set of probabilities. The strongest being; lack of a root directive.
(the gem also doesn't work for the default rails starter page)
But upon setting a custom root page; the gem works. So I did some monkey patching and added the solidus' root page to my project then appended the application routes to include the solidus home page.
config/routes.rb
Rails.application.routes.draw do
root to: 'spree/home#index'
mount Spree::Core::Engine, at: '/'
end
This has proven unsuccessful. I am using lighthouse to audit the application and the error signifies that the serviceworker is not being registered.
What am I missing? Is something out of scope?
I finally got it to work :) . The gem supplying the application layout is solidus but the problem is that the manifest is in the local application within which solidus is a gem.
To make it visible to the gem; I removed the tags from
and then put them in the gems layout file. You have to download it locally to make changes. The layout file as of writing this is at
but the head section contains a render of a _head partial at
from where it is more efficient to place these tags inside to resolve the issue.