0

I have a gulp setup that puts all my html in template cache for faster access in angular. I'm trying to add a service worker to my project, using sw-precache, so that it can be used offline. If I'm connected to the network, everything works fine. When I go offline, the requests for html resources (that are in the template cache) fail because it seems it is requesting the path from the network.

Is there something I need to add to my sw-precache config in order to have it defer to angular to handle retrieval of html files?

JakeHova
  • 1,189
  • 2
  • 15
  • 36
  • 0 down vote accept What I ended up doing was getting rid of the angular template cache and just using the service worker to handle the caching of all the markup instead. The responsiveness of the site is pretty much the same and it works offline now. – JakeHova Jun 28 '17 at 14:28

2 Answers2

2

ok, so this is how I solved this. I am using Angular JS 1.6.4 with sw-precache.

I have CacheStorage via service workers, so using service workers I know I am expecting devices to support certain functionality, in my case we know our users will have Android Tablets with Chrome and support is valid.

I am developing a progressive web app with offline functionality.

So, the theory...I have directives which have templateUrls.

Using this post: https://thinkster.io/templatecache-tutorial

I basically have my directive code:

angular.module('app').directive('location',
['$timeout', 'notify.service', 'user.settings.service', 'log.service',
    function ($timeout, notify, userSettings, log) {
        return {
            restrict: 'EA',
            ... controller etc.., 
            templateUrl: '/App/core/directives/location.html'
        }
    }
]);

Now, when this app goes offline, the cached instances of the content was not kicking it - annoying.

So, after much procrastinating I got down and dirty.

My solutio is, keep the templateUrl as it is, but overwrite the content via the $templateCache service.

To do this, you append a RUN function with your directive (for clarity). We know the service worker cache representation of our Url files contains the common path, in my case: '/App/core/directives/location.html'.

So, using new technology in the browser, window.caches gives me access to the CacheStorage that the service workers uses, I can then use the API available: https://developer.mozilla.org/en-US/docs/Web/API/Cache

I can then use the match method to find the matching service worker cache content, read that stream of binary and convert to HTML and then tell $templateCache to replace it with the service worker cached value.

So, for completeness (and you can create a common service which replaces the cached values based on templateUrl - which I will be doing for each directive)

(function () {

    'use strict';

    var templateUrl = '/App/core/directives/location.html';

    // <location on-location='someFunc'></location>
    // provides a form/control to find a location either by GEO location or manual city search
    angular.module('app')
            .run(['$templateCache', function ($templateCache) {
                var cache = window.caches;

                cache.match(templateUrl, { ignoreSearch: true }).then(function (response) {

                    if (response) {
                        response.body.getReader().read().then(function (cachedResponse) {
                            // convert the Uint8Array value to HTML string
                            var content = new TextDecoder('utf-8').decode(cachedResponse.value);
                            $templateCache.put(templateUrl, content);
                            //console.log($templateCache.get(templateUrl)); // debug
                        });
                    }
                });


            }])
    .directive('location',
    ['$timeout', 'notify.service', 'user.settings.service', 'log.service',
        function ($timeout, notify, userSettings, log) {
            return {
                restrict: 'EA',
                ... controller, scope etc...
                templateUrl: templateUrl
            }
        }
    ]);  
})();

Draw backs...the RUN process is synchronous, so initially they have to hit the site online first...but thats how service worker needs to work anyway, so thats handled in training :)

I expect there to be a better option, but for the time being thats the solution I have, I will be creating a template service for replacing $templateCache values based on the var templateUrl each directive will have, so the code becomes cleaner in each directtive....i considered having a global arr of templates and files, but, just a bit obscure, think its cleaner for each directive

1

my original solution was not 100%

To solve this, use sw-precache and sw-toolbox

Using a gulp configuration you can setup sw-precache to cache you content and extend this with sw-toolbox to use cached responses based upon routing configuration

see: https://developers.google.com/web/ilt/pwa/using-sw-precache-and-sw-toolbox

  • That toolbox.router is what I was looking for. Your original answer worked, but I needed it to work offline first and I also just had too many components to go back and alter code paths themselves. The sw.toolbox solution allows me to just explcitly state that any requests for html/jpg within the app directory should go cache first. From my preliminary tests (haven't tested the whole site) it looks like that works correctly. – JakeHova Jul 12 '17 at 18:53
  • yeh its great, I have now refactored and removed my original solution, when you have sw-toolbox set up you no longer need it, you can just have templateUrls and any requests you specify in your sw-routings are handled by cache – Paul Backhouse Jul 13 '17 at 19:04