0

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?

kevin Mucheru
  • 27
  • 1
  • 7
  • Is your application layout used with that setup? I can't tell from this whether your application layout is being used or perhaps the gem's engine provides its own. If it's the latter, then your application js wouldn't load and subsequently register your serviceworker. – rossta Sep 20 '18 at 20:07
  • The solidus gem comes with it's default layouts. I think here lies the problem. Adding the gem's files to the project and modifying them doesn't seem to be working either. So far; the gem seems to be overriding anything that interferes with the gem's assets. Adding a custom root page that requires the application's layout might solve this. – kevin Mucheru Sep 21 '18 at 13:37

1 Answers1

0

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

app/views/layouts/application.html.erb

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

app/views/spree/layouts/

but the head section contains a render of a _head partial at

app/views/spree/shared/_head.html.erb

from where it is more efficient to place these tags inside to resolve the issue.

<%= javascript_include_tag "application" %>
<link rel="manifest" href="/manifest.json" />
<meta name="apple-mobile-web-app-capable" content="yes">
kevin Mucheru
  • 27
  • 1
  • 7