Merge pull request #613 from jeffposnick/material-sprint

Service-worker based caching using sw-precache
master
Addy Osmani 2015-02-01 21:43:38 +00:00
commit 4090e3df83
4 changed files with 109 additions and 2 deletions

View File

@ -19,6 +19,55 @@
(function() {
'use strict';
// Check to make sure service workers are supported in the current browser,
// and that the current page is accessed from a secure origin. Using a
// service worker from an insecure origin will trigger JS console errors. See
// http://www.chromium.org/Home/chromium-security/prefer-secure-origins-for-powerful-new-features
if ('serviceWorker' in navigator &&
(window.location.protocol === 'https:' ||
window.location.hostname === 'localhost' ||
window.location.hostname.indexOf('127.') === 0)) {
navigator.serviceWorker.register('/service-worker.js', {
scope: './'
}).then(function(registration) {
// Check to see if there's an updated version of service-worker.js with
// new files to cache:
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-registration-update-method
if (typeof registration.update === 'function') {
registration.update();
}
// updatefound is fired if service-worker.js changes.
registration.onupdatefound = function() {
// updatefound is also fired the very first time the SW is installed,
// and there's no need to prompt for a reload at that point.
// So check here to see if the page is already controlled,
// i.e. whether there's an existing service worker.
if (navigator.serviceWorker.controller) {
// The updatefound event implies that registration.installing is set:
// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#service-worker-container-updatefound-event
var installingWorker = registration.installing;
installingWorker.onstatechange = function() {
switch (installingWorker.state) {
case 'installed':
// At this point, the old content will have been purged and the
// fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in the page's interface.
break;
case 'redundant':
throw 'The installing service worker became redundant.';
}
};
}
};
}).catch(function(e) {
console.error('Error during service worker registration:', e);
});
}
// Your custom JavaScript goes here
})();

4
app/service-worker.js Normal file
View File

@ -0,0 +1,4 @@
// This file is intentionally without code.
// It's present so that service worker registration will work when serving from the 'app' directory.
// The version of service-worker.js that's present in the 'dist' directory is automatically
// generated by the 'generate-service-worker' gulp task, and contains code to precache resources.

View File

@ -27,6 +27,10 @@ var runSequence = require('run-sequence');
var browserSync = require('browser-sync');
var pagespeed = require('psi');
var reload = browserSync.reload;
var swPrecache = require('sw-precache');
var fs = require('fs');
var path = require('path');
var packageJson = require('./package.json');
// Lint JavaScript
gulp.task('jshint', function() {
@ -211,7 +215,11 @@ gulp.task('serve:dist', ['default'], function() {
// Build Production Files, the Default Task
gulp.task('default', ['clean'], function(cb) {
runSequence('styles', ['jshint', 'html', 'scripts', 'images', 'styleguide-images', 'fonts', 'copy'], cb);
runSequence(
'styles',
['jshint', 'html', 'scripts', 'images', 'styleguide-images', 'fonts', 'copy'],
'generate-service-worker',
cb);
});
// Run PageSpeed Insights
@ -225,5 +233,50 @@ gulp.task('pagespeed', function (cb) {
}, cb);
});
// See http://www.html5rocks.com/en/tutorials/service-worker/introduction/ for
// an in-depth explanation of what service workers are and why you should care.
// Generate a service worker file that will provide offline functionality for
// local resources. This should only be done for the 'dist' directory, to allow
// live reload to work as expected when serving from the 'app' directory.
gulp.task('generate-service-worker', function(callback) {
var rootDir = 'dist';
swPrecache({
// Used to avoid cache conflicts when serving on localhost.
cacheId: packageJson.name || 'web-starter-kit',
// URLs that don't directly map to single static files can be defined here.
// If any of the files a URL depends on changes, then the URL's cache entry
// is invalidated and it will be refetched.
// Generally, URLs that depend on multiple files (such as layout templates)
// should list all the files; a change in any will invalidate the cache.
// In this case, './' is the top-level relative URL, and its response
// depends on the contents of the file 'dist/index.html'.
dynamicUrlToDependencies: {
'./': [path.join(rootDir, 'index.html')]
},
staticFileGlobs: [
// Add/remove glob patterns to match your directory setup.
rootDir + '/fonts/**/*.woff',
rootDir + '/images/**/*',
rootDir + '/scripts/**/*.js',
rootDir + '/styles/**/*.css',
rootDir + '/*.{html,json}'
],
// Translates a static file path to the relative URL that it's served from.
stripPrefix: path.join(rootDir, path.sep)
}, function(error, serviceWorkerFileContents) {
if (error) {
return callback(error);
}
fs.writeFile(path.join(rootDir, 'service-worker.js'),
serviceWorkerFileContents, function(error) {
if (error) {
return callback(error);
}
callback();
});
});
});
// Load custom tasks from the `tasks` directory
// try { require('require-dir')('tasks'); } catch (err) { console.error(err); }

View File

@ -25,7 +25,8 @@
"opn": "^1.0.0",
"psi": "^1.0.4",
"require-dir": "^0.1.0",
"run-sequence": "^1.0.2"
"run-sequence": "^1.0.2",
"sw-precache": "^1.2.1"
},
"engines": {
"node": ">=0.10.0"