Начало работы с PWA

внешний интерфейс сервер Promise PWA

Простое вводное руководство по PWA

Что такое ПВА

MDNНа официальном сайте есть очень четкое определение PWA.

Progressive web apps (PWAs) take traditional web sites/applications — with all of the advantages the web brings — and add a number of features that give them many of the user experience advantages of native apps. 

Проще говоря: PWA похожи на традиционные веб-приложения, но лучше.

PWA — это технология, запущенная Google, вы можетездесьНайдите больше деталей. или перейти кMDNОзнакомьтесь с документацией.

Знание подготовки к PWA

PWA совершенно новый.Это не просто совершенно новый API, но, что более важно, он вводит новый набор стандартов и синтаксиса в качестве основы. Прежде чем изучать PWA, вам необходимо убедиться, что вы умеете использовать следующее:

  1. Стандартный синтаксис ES6
  2. Обещанный стандарт, это самый важный пункт знаний, если вы не знакомы с ним или не слышали о нем, то вам придется подумать об этом.
  3. fetch, новый API для получения ресурсов, он включает в себя Request, Response, Header и Stream
  4. WebWorker, решение JavaScript для одного потока
  5. Кэш API

Легкие ошибки PWA

При развертывании PWA в Интернете убедитесь, что он использует HTTPS, а не HTTP. Разумеется, для простоты разработки браузер поддерживаетlocalhostРазвернуть выше.

После того, как PWA завершит кеширование, много раз вы обнаружите, что код не может быть изменен или рабочий процесс не обновляется автоматически, как ожидалось.В это время вы можете попытаться очистить кеш.

PWA поддерживаются не всеми браузерами, на самом деле очень немногие браузеры поддерживают PWA по умолчанию. Chrome и FireFox в этом отношении лучше, поэтому в этой статье в качестве инструмента разработки используется Chrome.

некоторая подготовка

Во-первых, давайте начнем с некоторых простых приготовлений. PWA нужен сервер, мы используем Koa, чтобы просто построить сервер. Сначала создайте каталог разработки и инициализируйте некоторые файлы:

mkdir pwa-test
cd pwa-test
touch index.html
touch index.js
touch sw.js

// 服务器脚本
touch server.js

// 初始化nodejs项目目录,一路回车
npm init

Затем установите некоторые пакеты разработки

npm install koa koa-static --save-dev
//或者
yarn add koa koa-static --dev

Далее мыserver.jsНапишите в нем следующий простой код:

const Koa = require('koa');
const Static = require('koa-static');
const path = require('path');  

const app = new Koa();
const staticPath = './';

app.use(Static(path.resolve(__dirname, staticPath)));

app.listen(8080);

затем вindex.htmlНапишите в нем какой-нибудь простой контент

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>PWA TEST</title>
</head>
<body>
    <script src="./index.js"></script>
</body>
</html>

Начните свое путешествие в PWA

service worker

Одна из самых важных частей PWA,service worker. Он похож, но отличается от традиционного рабочего. действоватьService WorkerСпособ очень простой, нужна простая регистрация. Далее мы вводим конкретное использование.

Во-первых, проверить, поддерживает ли онservice worker:

// index.js
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/sw.js').then(reg => {
        console.log('service worker registed!');
    }).reject(err => {
        console.log('Opooos, something wrong happend!');
    })
}

window.onload = function() {
    document.body.append('PWA!')
}

Этот код использует обещания, которые возвращают обещание при регистрации файла. Стоит отметить, что полученный по регистру файл — это не путь относительно пути, где находится текущий файл, а относительный путь корневого пути. Другими словами, если ваше приложение pwa находится вhttps://www.example.com/pwaНа ходу, то вы регистрируетеsw.jsнет./sw.js, но должно быть/pwa/sw.js.

Теперь у нас есть зарегистрированный сервис-воркер, но у него пока нет контента. Затем мы пишем следующий код в sw.js:

// sw.js
self.addEventListener('install', function (e) {
    e.waitUntil(
        caches.open('v1').then(cache => {
            return cache.addAll([
                '/index.js',
                '/index.html',
                '/'
            ]);
        })
    );
});

self.addEventListener('fetch', function (event) {
    event.respondWith(
        caches.match(event.request)
        .then(function (response) {
            // 检测是否已经缓存过
            if (response) {
                return response;
            }

            var fetchRequest = event.request.clone();

            return fetch(fetchRequest).then(
                function (response) {
                    // 检测请求是否有效
                    if (!response || response.status !== 200 || response.type !== 'basic') {
                        return response;
                    }

                    var responseToCache = response.clone();

                    caches.open('v1')
                        .then(function (cache) {
                            cache.put(event.request, responseToCache);
                        });

                    return response;
                }
            );
        })
    );
});

selfВ Worker это эквивалентноGlobal, здесь мы регистрируем два события:installа такжеfetch. Эти два события соответствуютservice WorkerВызывается при установке и скачивании файлов.

прежде всегоinstall, когда вы регистрируете файл, будет вызвана установка, что означает, что файл будет установлен в сервис-воркере.installмероприятиеeventEстьwaitUntilФункция, которая принимает Promise в качестве параметра. Это гарантирует, что установка не будет завершена до тех пор, пока входящее обещание не будет выполнено.

существуетwaitUntilВнутри мы использовалиcaches. Это глобальная переменная, мы используемopenОткройте кеш, скажем, библиотека кеша называетсяv1, если нет, то он будет создан автоматически.

caches.open('v1')Также возвращает обещание, функция обратного вызова которого получаетcache, которая является соответствующей библиотекой кэша. Далее мы используемaddAllДобавлен/index.jsа также/index.htmlэти два файла. Помните, операции с кешем должны возвращаться, иначе waitUntil не получит указаний о том, когда завершить установку.

другое событиеfetchДля чего это? Он будет «перехватывать» запросы на выборку веб-страниц. Таким образом, мы можем заблокировать часть или всю веб-страницу.fetchЗапросить, а потом посмотреть, есть ли в нашем кеше запрошенные этими запросами файлы, и если есть, то взять прямо из кеша, не скачивая его. Это также одна из наиболее важных особенностей PWA.

self.addEventListener('fetch', function (event) {
    event.respondWith(
        caches.match(event.request)
        .then(function (response) {

            if (response) {
                return response;
            }

            var fetchRequest = event.request.clone();

            return fetch(fetchRequest).then(
                function (response) {

                    if (!response || response.status !== 200 || response.type !== 'basic') {
                        return response;
                    }

                    var responseToCache = response.clone();

                    caches.open('v1')
                        .then(function (cache) {
                            cache.put(event.request, responseToCache);
                        });

                    return response;
                }
            );
        })
    );
});

Во-первых, когда делается запрос на выборку,fetchсобытие называется.fetchмероприятиеeventВ нем также есть особое свойство, т.request. и тот, что внутри nodejsrequestТочно так же он представляет собой запрос.

Сначала ищем это в кешеrequestРанее не существовал, позвонитьmatchФункция, она возвращает обещание, которое призывает один, когда это обещание успешноresponseФункция обратного вызова в качестве параметра. Если файл, соответствующий запросу, найден в кеше, тоresponseне дляundefined, затем вернитесь напрямую.

Но вопрос в том, как сказать основному потоку: «Этот файл скачан, и он у меня в кеше, просто зайди и возьми».eventЕсть еще метод,event.respondWithМетоды. Он принимает промис в качестве параметра, успешный обратный вызов этого промиса должен бытьresponse.

Если он не найден, то он должен быть загружен с сервера. Конечно, мы также хотим добавить этот файл в кеш, чтобы не загружать его каждый раз.

Мы используемfetchвместоajaxВажная причина в том, что,fetchестественная поддержкаRequestа такжеResponse,并且是使用的Promise。 с участиемservice Workerпредставляет собой набор.

fetchполучитьrequestКак запрос и вернуть этот запрос в функцию обратного вызоваresponse.

Примечательно,requestа такжеresponseвсе потоки и nodejsStreamаналогичный. Итак, если мы прямо положимevent.requestперейти кfetch,Такrequestнельзя использовать повторно. Итак, мы копируемrequestзапросить, чтобы его можно было использовать повторно. Когда запрос успешен (запрос на выборку успешен, это не означает, что данные получены. В отличие от ajax, он не успешен только тогда, когда возникает ошибка, которая приводит к сбою запроса. В других случаях, даже если запрос 404, это не будет успешным. успех), мы судим, получил ли ответ что-нибудь, и это200успешно, иначе нельзя跨域получено (т.response.type == 'basic').

Хорошо, теперь, когда мы получили этот ответ от сервера, нам просто нужно добавить его в наш кеш. Здесь мы звонимcache.putкэшировать ответ на этот запрос.

Наконец, не забудьте вернуться к этому ответу! А для повторного использования возвращенный надо клонировать! потому чтоevent.respondWithВам нужно сказать основному потоку: «У нас есть этот запрос (будь то из кеша или с сервера), просто примите ответ!»

Все готово

Теперь у нас все готово, посмотрим, сработает ли это. Откройте терминал и запустите скрипт сервера

nodejs ./server.js

Открытьlocalhost:8080, вы должны быть в состоянии увидетьPWA!.

Теперь мы останавливаем серверный скрипт и снова обновляем страницу. На странице также должно отображатьсяPWA!.

некоторые проблемы

  1. Как обновить сервис-воркер?

    Это очень просто, вам нужно только изменить sw.js, он будет активно определять и сравнивать при следующем подключении к Интернету, и если он будет другим, он будет переустановлен.

  2. Как обновить кешированный скрипт или файл?

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

  3. Есть ли успешные примеры, на которых можно поучиться?

    Да, откройте китайский официальный сайт Vue с помощью Chrome, и вам будет предложено присоединиться к рабочему столу.После согласия вы откроете для себя магию pwa.

  4. Почему мой PWA не поддерживается на мобильных телефонах?

    Вам нужно установить Chrome или Firefox и предоставить ему некоторые основные разрешения, например разрешить создавать значки на рабочем столе.

  5. Вроде в pwa ничего нет, разве не разрешается только оффлайн доступ?

    Нет! PWA может не только этот контент! PWA может даже вызвать некоторые из исходных приложений для вызова интерфейса или отправить сообщение как родное приложение!

  6. Отлично, как я могу продолжать учиться!

    У вас есть два варианта,MDNДокументы на него есть, но китайского упрощенного нет, только китайский традиционный.Официальный сайт PWA, нужен научный доступ в Интернет.