Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Implementing serviceWorker for offline usage
  • Loading branch information
SaschaDens committed Mar 28, 2016
commit 1b6f68f1166074ed3f251279a0a124e4bc12d377
90 changes: 82 additions & 8 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ var browserify = require('browserify');
var watchify = require('watchify');
var browserSync = require('browser-sync');
var runSequence = require('run-sequence');
var swPrecache = require('sw-precache');
var rev = require('gulp-rev');
var revReplace = require('gulp-rev-replace');
var path = require('path');
var pkg = require('./package.json');

var staticAssets = [
"index.html",
Expand Down Expand Up @@ -77,7 +82,7 @@ gulp.task('copy-js-templates', function (cb) {
var assets = "js/*.template.js";
gulp.src(assets, {base: './js'})
.pipe(gulp.dest('build/js/'))
.on("finish", function() {
.on("finish", function () {
cb();
});
});
Expand Down Expand Up @@ -141,12 +146,17 @@ gulp.task('clean-pre-build', function () {

gulp.task('clean-post-build', function () {
return gulp.src([
'./build/js/index.template.js',
'./build/js/scripts.min.js.map',
'./build/js/checkSupport.template.js',
'./build/js/analytics.template.js',
'./build/assets/spinner*.gif'
], {read: false})
'./build/js/index.template.js',
'./build/js/scripts.min.js.map',
'./build/js/checkSupport.template.js',
'./build/js/analytics.template.js',
'./build/assets/spinner*.gif',

'./build/js/scripts.min.js',
'./build/js/regExWorker.template.js',
'./build/css/regexr.css',
'./build/rev-manifest.json'
], {read: false})
.pipe(rimraf());
});

Expand All @@ -161,11 +171,72 @@ gulp.task('inline', function () {

gulp.task('parse-index', function () {
return gulp.src('build/index.html')
.pipe(template({noCache: Date.now()}))
.pipe(minifyHTML())
.pipe(gulp.dest('build/'));
});

gulp.task('copy-sw-scripts', function () {
return gulp
.src([
'node_modules/sw-toolbox/sw-toolbox.js',
'js/sw/runtime-caching.js'
])
.pipe(gulp.dest('build/js/sw'));
});

gulp.task('generate-service-worker', ['copy-sw-scripts'], function (callback) {
var rootDir = 'build';
var filePath = path.join(rootDir, 'service-worker.js');

return swPrecache.write(filePath, {
// Used to avoid cache conflicts when serving on localhost.
cacheId: pkg.name || 'RegExr',
// sw-toolbox.js needs to be listed first. It sets up methods used in runtime-caching.js.
importScripts: [
'js/sw/sw-toolbox.js',
'js/sw/runtime-caching.js'
],
staticFileGlobs: [
// Add/remove glob patterns to match your directory setup.
rootDir + '/assets/**/*',
rootDir + '/css/**/*.css',
rootDir + '/js/**/*.js',
rootDir + '/*.{html,json}'
],
// Translates a static file path to the relative URL that it's served from.
// This is '/' rather than path.sep because the paths returned from
// glob always use '/'.
stripPrefix: rootDir + '/'
});
});

gulp.task('revision', function () {
var rootDir = 'build';

return gulp.src([
rootDir + '/js/scripts.min.js',
rootDir + '/js/regExWorker.template.js',
rootDir + '/css/regexr.css'
], {base: 'build'})
.pipe(rev())
.pipe(gulp.dest('build'))
.pipe(rev.manifest())
.pipe(gulp.dest('build'));
});

gulp.task('revision-replace', ['revision'], function () {
var manifest = gulp.src('build/rev-manifest.json');

return gulp.src([
'build/index.html',
'build/js/scripts-*.min.js'
], {base: 'build'})
.pipe(revReplace({
manifest: manifest
}))
.pipe(gulp.dest('build'));
});

gulp.task('build', function (done) {
runSequence(
'clean-pre-build',
Expand All @@ -174,7 +245,9 @@ gulp.task('build', function (done) {
['minify-js', 'minify-css'],
['parse-index'],
'inline',
'revision-replace',
'clean-post-build',
'generate-service-worker',
'server', 'open-build',
done
);
Expand All @@ -184,6 +257,7 @@ gulp.task('default', function (done) {
runSequence(
['sass', 'watch-js', 'watch-sass', 'copy-js-templates'],
'copy-assets',
'generate-service-worker',
['watch-assets', 'watch-js-templates', 'browser-sync'],
done
);
Expand Down
8 changes: 4 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@
<meta property="og:url" content="http://regexr.com/"/>
<meta property="og:site_name" content="RegExr.com"/>

<script src="js/scripts.min.js?no=<%=noCache %>"></script>
<script src="js/regExWorker.template.js?no=<%=noCache %>"></script>
<script src="js/scripts.min.js"></script>
<script src="js/regExWorker.template.js"></script>

<link rel="stylesheet" href="css/regexr.css?no=<%=noCache %>">
<link rel="stylesheet" href="css/regexr.css">
<script src="//ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
</head>
<body>
Expand Down Expand Up @@ -216,7 +216,7 @@ <h1 class="tool-label"></h1>
<li class="button explain" data-tool="explain">Explain</li>
</ul>
</div>

<div class="tools editor replace"></div>
<div class="tools editor list"></div>
<div class="tools editor out"></div>
Expand Down
59 changes: 59 additions & 0 deletions js/index.template.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,65 @@ function createRegExr() {
}
}

// 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
var isLocalhost = Boolean(window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
)
);

if ('serviceWorker' in navigator &&
(window.location.protocol === 'https:' || isLocalhost)) {
navigator.serviceWorker.register('service-worker.js')
.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 new Error('The installing ' +
'service worker became redundant.');

default:
// Ignore
}
};
}
};
}).catch(function(e) {
console.error('Error during service worker registration:', e);
});
}

if (window["WebFont"] != null) {
try {
WebFont.load({
Expand Down
10 changes: 10 additions & 0 deletions js/sw/runtime-caching.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(function (global) {
'use strict';

// See https://github.com/GoogleChrome/sw-toolbox/blob/6e8242dc328d1f1cfba624269653724b26fa94f1/README.md#toolboxroutergeturlpattern-handler-options
// and https://github.com/GoogleChrome/sw-toolbox/blob/6e8242dc328d1f1cfba624269653724b26fa94f1/README.md#toolboxfastest
// for more details on how this handler is defined and what the toolbox.fastest strategy does.
global.toolbox.router.get('/(.*)', global.toolbox.fastest, {
origin: /\.(?:googleapis|gstatic)\.com$/
});
})(self);
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"gulp-minify-css": "^1.2.1",
"gulp-minify-html": "^1.0.4",
"gulp-open": "^1.0.0",
"gulp-rev": "^7.0.0",
"gulp-rev-replace": "^0.4.3",
"gulp-rimraf": "^0.2.0",
"gulp-sass": "^2.1.0",
"gulp-sourcemaps": "^1.6.0",
Expand All @@ -21,6 +23,8 @@
"gulp-watch": "^4.3.5",
"html-minifier": "^0.7.2",
"run-sequence": "^1.1.5",
"sw-precache": "^3.1.1",
"sw-toolbox": "^3.1.1",
"uglify-js": "^2.4.23",
"vinyl-buffer": "^1.0.0",
"vinyl-source-stream": "^1.1.0",
Expand Down