Недавно я участвовал в AngularAttack 2016 Hackathon и создал Let Me See: приложение, которое помогает людям с потерей зрения увидеть мир. Это приложение было создано с использованием Ionic2 (и, конечно, Angular2). Но больше всего мне хотелось, чтобы приложение было прогрессивным, поэтому я добавил поддержку автономного кэширования - для лучшей мгновенной загрузки. Позвольте мне показать вам, как я просто и быстро добавил, что ...

Ой! Кстати, «Let Me See» выиграла приз за инновации!

Прежде чем мы начнем, я предполагаю, что у вас уже есть существующее веб-приложение. Я собираюсь использовать «Дай мне увидеть» в качестве примера, но шаги, которые мы собираемся пройти вместе, применимы к любому современному одностраничному приложению.

Давайте начнем. Вот структура нашего приложения ...

Как видите, это простое приложение Ionic2 с некоторыми дополнительными файлами конфигурации для Firebase, поскольку приложение размещено на Firebase. Но давайте поговорим об этом в другом сообщении в блоге.

Следует обратить внимание на наличие файла sw-precache-config.json. Этот файл используется инструментом Service Worker Precache (sw-precache).

Tl; Dr: Service Worker Precache позволяет нам предварительно кэшировать все необходимые ресурсы, необходимые оболочке приложения. Он также автоматически генерирует для нас рабочий файл сервера!

Вот как работает инструмент sw-precache

Во-первых, вы должны решить, хотите ли вы использовать этот инструмент глобально в качестве интерфейса командной строки (CLI):

$ npm install --global sw-precache

И используйте это так:

$ sw-precache --sw-file='www/sw.js' \
              --static-file-globs='www/**/*.html'

Или локально с вашей системой сборки:

$ npm install --save-dev sw-precache

И используйте его со своей собственной системой сборки (Gulp, Webpack…).

Затем нам нужно предоставить файл конфигурации: sw-precache-config.json. Вот как он выглядит для нашего приложения «Let Me See»:

{
  "swFile": "www/sw.js",
  "staticFileGlobs": [
    "www/manifest.json",
    "www/**/*.css",
    "www/**/*.{ttf,woff,woff2,eof}",
    "www/**/*.js",
    "www/**/*.html",
    "www/**/*.{png,jpg,gif,svg,mp3}"
  ],
  "handleFetch": true,
  "stripPrefix": "www/",
  "cacheId": "let-me-see-v1",
  "maximumFileSizeToCacheInBytes": 4194304,
  "ignoreUrlParametersMatching": "[/./]",
  "verbose": true
}

Позвольте мне быстро объяснить некоторые из этих вариантов:

  • swFile: путь к файлу сервис-воркера, который будет сгенерирован (эта опция не задокументирована - см. этот файл);
  • staticFileGlobs: массив из одного или нескольких строковых шаблонов. Это файлы, которые будут кэшироваться и использоваться в автономном режиме;
  • handleFetch: определяет, включен ли обработчик событий fetch в сгенерированный код сервис-воркера;
  • cacheId: строка, используемая для различения кешей;
  • maximumFileSizeToCacheInBytes: устанавливает максимально допустимый размер файла в списке предварительного кеширования (добро пожаловать);
  • stripPrefix: удаляет указанную строку из начала URL-адреса пути во время выполнения.

Вы можете прочитать более подробную документацию по этим параметрам в репозитории github.

Теперь, когда у нас установлен и готов инструмент sw-precache. Нам нужно заставить его работать с нашим приложением. Я предпочитаю использовать sw-precache в качестве задачи Gulp, потому что Ionic2 использует его как систему сборки. Он даже предоставляет хуки, куда вы можете добавлять свои собственные задачи сборки.

Итак, давайте создадим нашу задачу Gulp sw:

gulp.task('sw', function(callback) {
  var path = require('path');
  var swPrecache = require('sw-precache');
  var rootDir = 'www';
  var options = require('./sw-precache-config.json');
  options.ignoreUrlParametersMatching = [/./];
  swPrecache.write(path.join(rootDir, 'sw.js'), options, callback);
});

Затем мы вызываем нашу задачу после задачи сборки, чтобы инструмент sw-precache мог сгенерировать для нас Server Worker после завершения сборки:

//...
gulp.task('build:after', ['sw']);
//...

При желании мы также можем запустить задачу sw во время задачи watch. Это означает, что служебный воркер будет автоматически генерироваться каждый раз, когда вы редактируете файл в своем приложении:

gulp.task('watch', ['clean'], function(done){
  runSequence(
    ['sass', 'html', 'fonts', 'scripts'],
    'sw',
    function(){ //...

Я также настоятельно рекомендую вам отключить параметр handleFetch, который в основном отключает событие fetch. В противном случае контент всегда будет обслуживаться из кеша сервис-воркера; и ваша настройка живой перезагрузки может работать не так, как ожидалось.

Вот и все. Вы сделали!

Вы только что добавили автономную поддержку своего веб-приложения. Вы можете увидеть полностью автоматически сгенерированный сервис-воркер для Let Me See здесь, на github.

И последнее, но не менее важное: не забудьте зарегистрировать этого сервис-воркера в своем index.html:

<script>
   if('serviceWorker' in navigator) {
     navigator.serviceWorker.register('sw.js');
   }
</script>


Подпишитесь на @manekinekko, чтобы узнать больше о веб-платформе.