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?

1
  • 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. Commented Jun 28, 2017 at 14:28

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

Comments

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

2 Comments

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.
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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.