Прогрессивное веб-приложение (PWA) Blazor ASP .NET Core

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.

Внимание

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

В текущем выпуске см . версию .NET 8 этой статьи.

Прогрессивное веб-приложение Blazor — это одностраничное приложение (SPA), которое использует API и функциональные возможности современного браузера, реализуя свойственное классическим приложениям поведение.

Blazor WebAssembly — это стандартизированная клиентская платформа веб-приложений с поддержкой API любых браузеров, в том числе API-интерфейсы прогрессивных веб-приложений (PWA), требуемых для реализации следующих возможностей:

  • работа в автономном режиме и мгновенная загрузка вне зависимости от скорости сети;
  • возможность запуска в отдельном окне приложения, а не только в окне браузера;
  • запуск из меню "Пуск", меню закрепления или с начального экрана основной операционной системы (ОС);
  • получение push-уведомлений от внутреннего сервера, даже если пользователь не работает с приложением;
  • автоматическое обновление в фоновом режиме.

Слово прогрессивное используется для описания таких приложений по следующим причинам:

  • на начальном этапе пользователь может открывать и использовать приложение в своем веб-браузере аналогично любому другому одностраничному приложению;
  • затем его можно установить в своей ОС и включить push-уведомления.

Создание проекта на основе шаблона PWA

При создании приложения Blazor WebAssembly установите флажок Прогрессивное веб-приложение.

При необходимости PWA можно настроить для приложения, созданного из шаблона проекта ASP.NET Core HostedBlazor WebAssembly . Сценарий прогрессивного веб-приложения не зависит от модели размещения.

Преобразование существующего приложения Blazor WebAssembly в PWA

В этом разделе приводятся указания по преобразованию существующего приложения Blazor WebAssembly в PWA.

В файле проекта приложения сделайте следующее:

  • Добавьте указанное ниже свойство ServiceWorkerAssetsManifest в PropertyGroup:

      ...
      <ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
    </PropertyGroup>
    
  • Добавьте указанный ниже элемент ServiceWorker в ItemGroup:

    <ItemGroup>
      <ServiceWorker Include="wwwroot\service-worker.js" 
        PublishedContent="wwwroot\service-worker.published.js" />
    </ItemGroup>
    

Для получения статических ресурсов воспользуйтесь одним из следующих подходов:

  • Создайте отдельный новый проект PWA с помощью команды dotnet new в командной оболочке:

    dotnet new blazorwasm -o MyBlazorPwa --pwa
    

    В предыдущей команде параметр -o|--output создает новую папку для приложения с именем MyBlazorPwa.

    Если вы не преобразуете приложение для использования в последнем выпуске, передайте параметр -f|--framework. В следующем примере создается приложение для ASP.NET Core версии 5.0:

    dotnet new blazorwasm -o MyBlazorPwa --pwa -f net5.0
    
  • Перейдите по приведенному ниже URL-адресу в репозиторий GitHub для ASP.NET Core, который содержит ссылки на справочные материалы и ресурсы для ветви main. Выберите выпуск, с которым вы работаете, в раскрывающемся списке Switch branches/tags (Переключение ветвей или тегов).

    Blazor WebAssembly Папка шаблона wwwroot проекта (dotnet/aspnetcore ветвь репозитория main GitHub)

    Примечание.

    По ссылкам в документации на справочные материалы по .NET обычно загружается ветвь репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающийся список Switch branches or tags (Переключение ветвей или тегов). Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).

    Скопируйте следующие файлы из папки wwwroot источника в созданном вами приложении или из справочных ресурсов в репозитории GitHub dotnet/aspnetcore в папку wwwroot приложения:

    • icon-192.png
    • icon-512.png
    • manifest.webmanifest
    • service-worker.js
    • service-worker.published.js

В файле wwwroot/index.html приложения:

  • Добавьте элементы <link> для манифеста и значка приложения:

    <link href="manifest.webmanifest" rel="manifest" />
    <link rel="apple-touch-icon" sizes="512x512" href="icon-512.png" />
    <link rel="apple-touch-icon" sizes="192x192" href="icon-192.png" />
    
  • Перейдите к репозиторию ASP.NET Core GitHub по следующему URL-адресу, который ссылается на release/7.0 источник и ресурсы в ветви. Если вы используете версию ASP.NET Core позже 7.0, измените селектор версии документа, чтобы просмотреть обновленные рекомендации для этого раздела. Выберите выпуск, с которым вы работаете, в раскрывающемся списке Switch branches/tags (Переключение ветвей или тегов).

    Blazor WebAssembly Папка шаблона wwwroot проекта (dotnet/aspnetcore ветвь репозитория release/7.0 GitHub)

    Примечание.

    По ссылкам в документации на справочные материалы по .NET обычно загружается ветвь репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающийся список Switch branches or tags (Переключение ветвей или тегов). Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).

    Скопируйте следующие файлы из папки wwwroot источника в созданном вами приложении или из справочных ресурсов в репозитории GitHub dotnet/aspnetcore в папку wwwroot приложения:

    • favicon.png
    • icon-512.png
    • manifest.json
    • service-worker.js
    • service-worker.published.js

В файле wwwroot/index.html приложения:

  • Добавьте элементы <link> для манифеста и значка приложения:

    <link href="manifest.json" rel="manifest" />
    <link rel="apple-touch-icon" sizes="512x512" href="icon-512.png" />
    
  • Добавьте следующий тег <script> в закрывающий тег </body> сразу после тега скрипта blazor.webassembly.js:

        ...
        <script>navigator.serviceWorker.register('service-worker.js');</script>
    </body>
    

Установка и манифест приложения

При посещении приложения, созданного с использованием параметра шаблона прогрессивного веб-приложения, пользователи могут установить его в меню "Пуск", меню закрепления или на начальном экране своей операционной системы. Порядок применения этого параметра зависит от того, какой браузер используется. В классических версиях браузеров на основе Chromium, таких как Microsoft Edge или Chrome, в строке URL-адреса появляется кнопка Добавить. После того как пользователь нажмет кнопку Добавить, отобразится диалоговое окно подтверждения.

Диалоговое окно подтверждения в Google Chrome представляет кнопку

В iOS посетители могут установить прогрессивное веб-приложение с помощью кнопки Поделиться в браузере Safari, а также используя параметр Добавить на экран Home. В браузере Chrome для Android для этой цели следует нажать кнопку Меню в правом верхнем углу окна, а затем выбрать команду Добавить на экран Home.

После установки приложение будет открываться в отдельном окне без адресной строки.

Приложение

Чтобы настроить заголовок окна, цветовую схему, значок или другие сведения, используйте файл manifest.json в каталоге wwwroot проекта. Схема этого файла соответствует веб-стандартам. Дополнительные сведения см . в веб-документах MDN: манифест веб-приложения.

Поддержка автономного режима

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

Внимание

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

Предупреждение

Если вы планируете распространять прогрессивное веб-приложение с поддержкой автономного режима, следует обратить внимание на несколько важных предупреждений и предостережений. Эти сценарии присущи всем поддерживающим автономную работу прогрессивным веб-приложениям и не являются специфичными для Blazor. Не забудьте прочитать и понять эти предостережения, прежде чем делать предположения о том, как работает приложение с поддержкой автономного режима.

Чтобы ознакомиться с принципами поддержки автономного режима:

  1. Публикация приложения. Дополнительные сведения см. в статье Размещение и развертывание ASP.NET Core Blazor.

  2. Разверните приложение на сервере, который поддерживает протокол HTTPS, и получите доступ к приложению в браузере по его защищенному HTTPS-адресу.

  3. Откройте средства разработки браузера и убедитесь, что для узла на вкладке Приложение зарегистрирована рабочая роль службы.

    Вкладка

  4. Перезагрузите страницу и просмотрите вкладку "Сеть". Кэш рабочей роли службы или памяти перечислены в качестве источников для всех ресурсов страницы:

    Вкладка

  5. Чтобы убедиться, что для загрузки приложения браузеру не требуется доступ к сети:

    • Завершите работу веб-сервера и проверьте, как приложение продолжит работу в обычном режиме, включая перезагрузку страниц. Аналогичным образом приложение продолжает обычную работу при снижении скорости сетевого подключения.
    • Имитируйте работу в автономном режиме на вкладке Сеть.

    Вкладка

Поддержка работы в автономном режиме с помощью рабочей роли службы является веб-стандартом, не относящимся к Blazor. Дополнительные сведения о рабочих службах см . в веб-документации MDN: API рабочей роли службы. Дополнительные сведения о распространенных шаблонах использования для работников службы см. в Разделе Google Web: Жизненный цикл рабочей роли службы.

Шаблон прогрессивного веб-приложения Blazor создает два файла рабочей роли службы:

  • wwwroot/service-worker.js, который используется во время разработки;
  • wwwroot/service-worker.published.js, который используется после публикации приложения.

Чтобы использовать общую логику для этих двух файлов рабочих ролей службы, рассмотрите следующий подход.

  • Добавьте третий файл JavaScript для хранения общей логики.
  • Используйте self.importScripts, чтобы загрузить общую логику в оба файла рабочей роли службы.

Стратегия первичного обращения к кэшу

Встроенная рабочая роль службы service-worker.published.js выполняет разрешение запросов с применением стратегии первичного обращения к кэшу. Это означает, что даже при наличии доступа к сети или нового содержимого на сервере во всех возможных случаях рабочая роль службы отдает предпочтение возвращаемому из кэша содержимому.

Такая стратегия полезна по следующим причинам.

  • Во-первых, за счет этого повышается надежность. Состояние доступа к сети сложно определить однозначно, поскольку пользователь не всегда просто находится в подключенном или автономном режиме.

    • Даже при наличии подключения его скорость может быть настолько мала, что ожидание загрузки содержимого может быть нецелесообразно.
    • Для некоторых URL-адресов из сети могут возвращаться недопустимые результаты, как, например, в случае с порталом перехвата Wi-Fi, который блокирует или перенаправляет определенные запросы.

    Именно поэтому API navigator.onLine браузера не может считаться надежным источником, на который следует полагаться в приложении.

  • Во-вторых, это позволяет гарантировать корректность. При создании кэша автономных ресурсов рабочая роль службы хэширует содержимое, чтобы гарантировать получение полного и согласованного моментального снимка ресурсов по состоянию на один конкретный момент времени. В дальнейшем этот кэш используется в качестве атомарной единицы. Запрашивать более новые версии ресурсов из сети нецелесообразно, поскольку все данные, которые требуются, уже хранятся в кэше. Любые другие данные могут стать причиной несогласованности и несовместимости, например при попытке использовать версии сборок .NET, которые не компилировались вместе.

Если при развертывании новой версии рабочей роли службы необходимо запретить получение service-worker-assets.js браузера из своего HTTP-кэша, например, чтобы устранить временные ошибки целостности проверка при развертывании новой версии рабочей роли службы, обновите регистрацию wwwroot/index.html рабочей роли службы, указав updateViaCache значение none:

<script>
  navigator.serviceWorker.register('/service-worker.js', {updateViaCache: 'none'});
</script>

Обновления в фоновом режиме

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

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

  • Во время компиляции проект создает манифест ресурсов рабочей роли службы. По умолчанию это service-worker-assets.js. В нем перечислены все статические ресурсы, которые требуются для работы приложения в автономном режиме, например сборки .NET, файлы JavaScript и каскадные таблицы стилей, в том числе хэши содержимого. Рабочая роль службы загружает список ресурсов и использует его для определения ресурсов, которые требуется кэшировать.
  • Каждый раз, когда пользователь открывает приложение, браузер повторно запрашивает service-worker.js и service-worker-assets.js в фоновом режиме. Файлы сравниваются побайтово с существующей установленной рабочей ролью службы. Если сервер возвращает измененное содержимое для любого из этих файлов, рабочая роль службы пытается установить собственную новую версию.
  • При установке собственной новой версии рабочая роль службы создает новый отдельный кэш для автономных ресурсов и начинает заполнять кэш ресурсами, перечисленными в файле service-worker-assets.js. Эта логика реализуется в функции onInstall в файле service-worker.published.js.
  • Процесс завершается успешно, когда все ресурсы загружаются без ошибок и все хэши содержимого совпадают. В случае успешного выполнения новая рабочая роль службы переходит в состояние ожидания активации. Как только пользователь закроет приложение (т. е. все вкладки или окна, в которых оно отображается), новая рабочая роль службы становится активной и используется при последующем посещении приложения. Старая рабочая роль службы и ее кэш при этом удаляются.
  • Если процесс завершается неудачно, новый экземпляр рабочей роли службы отклоняется. При следующем посещении пользователя будет предпринята попытка выполнить процесс обновления еще раз в расчете на более высокое качество сетевого подключения и возможность выполнения необходимых запросов.

Настроить этот процесс можно, используя логику рабочей роли службы. Все перечисленные выше варианты не являются специфичными для Blazor, однако описывают стандартный способ использования шаблона прогрессивного веб-приложения. Дополнительные сведения см . в веб-документах MDN: API рабочей роли службы.

Принципы разрешения запросов

Как описывается выше в разделе Стратегия первичного обращения к кэшу, по умолчанию рабочая роль службы применяет стратегию первичного обращения к кэшу, то есть пытается по возможности всегда использовать кэшированное содержимое. Если для отдельного URL-адреса кэшированное содержимое отсутствует (например, в случае запроса данных из серверного API), рабочая роль службы использует обычные сетевые запросы, которые выполняются успешно только при наличии доступа к серверу. Эта логика реализуется в функции onFetch в файле service-worker.published.js.

Если компоненты приложения Razor запрашивают данные из серверных API и вам требуется удобный пользовательский интерфейс для обработки сбоев, связанных с отсутствием доступа к сети, то соответствующую логику необходимо реализовать в самих компонентах приложения. Например, используйте try/catch для запросов HttpClient.

Поддержка страниц, подготавливаемых к просмотру на сервере

Рассмотрим, что происходит при первом переходе пользователя к URL-адресу, например к /counter, или по любой другой прямой ссылке в приложении. В таких случаях вам не нужно возвращать кэшированное содержимое как /counter. Вместо этого нужно загрузить в браузер содержимое, кэшированное как /index.html, для запуска приложения Blazor WebAssembly. Такие начальные запросы называются запросами навигации в отличие от следующих запросов:

  • запросов subresource для получения изображений, таблиц стилей или других файлов;
  • запросов fetch/XHR для получения данных API.

По умолчанию рабочая роль службы использует для обработки запросов навигации специальную логику. Рабочая роль службы разрешает такие запросы путем возврата кэшированного содержимого для /index.html, независимо от того, какой URL-адрес запрашивается. Эта логика реализуется в функции onFetch в файле service-worker.published.js.

Если для некоторых URL-адресов в вашем приложении должен возвращаться подготавливаемый к просмотру на сервере код HTML (то есть для обслуживания /index.html не должен использоваться кэш), вам потребуется изменить логику рабочей роли службы. Если все URL-адреса, содержащие /Identity/, требуется обрабатывать как обычные сетевые запросы к серверу, следует изменить логику функции onFetch в файле service-worker.published.js. Найдите следующий код:

const shouldServeIndexHtml = event.request.mode === 'navigate';

Измените код следующим образом:

const shouldServeIndexHtml = event.request.mode === 'navigate'
  && !event.request.url.includes('/Identity/');

Если этого не сделать, то, независимо от наличия сетевого подключения, рабочая роль службы будет перехватывать запросы к таким URL-адресам и разрешать их с помощью /index.html.

Добавьте в проверку конечные точки для внешних поставщиков проверки подлинности. В следующем примере в проверку добавляется /signin-google для проверки подлинности Google:

const shouldServeIndexHtml = event.request.mode === 'navigate'
  && !event.request.url.includes('/Identity/')
  && !event.request.url.includes('/signin-google');

Для среды не требуется никаких действий, где содержимое Development всегда извлекается из сети.

Управление кэшированием ресурсов

Если в вашем проекте определено свойство MSBuild ServiceWorkerAssetsManifest, средства сборки Blazor создадут манифест ресурса рабочей роли службы с указанным именем. По умолчанию шаблон прогрессивного веб-приложения создает файл проекта со следующим свойством.

<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>

Этот файл помещается в выходной каталог wwwroot, откуда браузер может извлекать его посредством запроса /service-worker-assets.js. Чтобы просмотреть содержимое этого файла, откройте /bin/Debug/{TARGET FRAMEWORK}/wwwroot/service-worker-assets.js в текстовом редакторе. Не вносите изменения в этот файл, поскольку он создается заново при каждой сборке.

По умолчанию этот манифест содержит следующие данные:

  • Все управляемые Blazor ресурсы, в том числе сборки .NET и файлы среды выполнения .NET WebAssembly, которые требуются для работы в автономном режиме.
  • Все ресурсы, которые будут опубликованы в каталоге wwwroot приложения, такие как изображения, таблицы стилей и файлы JavaScript. К ним также относятся статические веб-ресурсы, предоставляемые в составе внешних проектов и пакетов NuGet.

Чтобы управлять получением и кэшированием этих ресурсов в рабочей роли службы, измените логику функции onInstall в файле service-worker.published.js. По умолчанию рабочая роль службы извлекает и кэширует файлы, соответствующие типичным расширениям имен веб-файлов, таким как .html.pdb , .css.jsи , а также типы файлов, относящиеся к Blazor WebAssemblyфайлам (все версии) и .dll.wasmфайлам (ASP.NET Core в .NET 7 или более ранней версии).

Чтобы включить другие ресурсы, отсутствующие в каталоге wwwroot приложения, определите дополнительные записи ItemGroup MSBuild, как показано в следующем примере.

<ItemGroup>
  <ServiceWorkerAssetsManifestItem Include="MyDirectory\AnotherFile.json"
    RelativePath="MyDirectory\AnotherFile.json" AssetUrl="files/AnotherFile.json" />
</ItemGroup>

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

Внимание

Добавление ServiceWorkerAssetsManifestItem не приводит к публикации файла в каталог wwwroot приложения. Управление выходными данными публикации следует организовать отдельно. В результате добавления ServiceWorkerAssetsManifestItem в манифесте ресурса рабочей роли службы лишь появляется дополнительная запись.

Push-уведомления

Как и любые аналоги, прогрессивные веб-приложения Blazor WebAssembly поддерживают получение push-уведомлений от внутреннего сервера. Сервер может отправлять такие уведомления в любое время, даже если приложение не используется активно (например, если другой пользователь выполняет действие, о котором требуется оповестить).

Механизм отправки push-уведомлений не зависит от Blazor WebAssembly, так как он реализуется на внутреннем сервере, который может использовать любую технологию. Для отправки push-уведомлений с сервера ASP.NET Core рекомендуется использовать методику, аналогичную описываемой в рамках семинара по проекту Blazing Pizza.

Механизм приема и отображения push-уведомлений на стороне клиента также реализуется независимо от Blazor WebAssembly в файле JavaScript рабочей роли службы. Рекомендуем обратиться к семинару, посвященному проекту Blazing Pizza.

Предупреждения относительно прогрессивных веб-приложений с поддержкой автономной работы

Поддержка работы в автономном режиме требуется не для всех приложений. С ее реализацией сопряжены определенные сложности, решение которых не всегда целесообразно.

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

  • Браузер использует преимущественно локальное основное хранилище данных. В качестве примера можно привести разработку пользовательского интерфейса для устройства Интернета вещей, которое хранит данные в localStorage или индексированной базе данных.
  • Приложение тратит значительный объем ресурсов на получение и кэширование данных серверного API для каждого пользователя, чтобы они могли работать с такими данными в автономном режиме. Если приложение должно поддерживать редактирование, потребуется создать систему, которая будет отслеживать изменения и синхронизировать их с серверной частью.
  • Необходимо гарантировать мгновенную загрузку приложения независимо от состояния сетевого подключения. Реализуйте соответствующий пользовательский интерфейс для работы с запросами к серверному API и корректного разрешения ситуаций, когда они завершаются сбоем из-за отсутствия доступа к сети.

Кроме того, поддержка работы в автономном режиме для прогрессивных веб-приложений сопряжена с рядом дополнительных сложностей. Разработчикам следует внимательно изучить предостережения, приведенные в разделах ниже.

Работа в автономном режиме поддерживается только для опубликованных приложений

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

При создании автономного приложения недостаточно для тестирования приложения в Development среде. Вам придется проверить приложение в опубликованном состоянии, чтобы понять, как оно будет вести себя при различных состояниях сети.

Обновление выполняется только после выхода пользователя из приложения

Обновления будут выполняться только после того, как пользователь выйдет из приложения на всех вкладках. Как поясняется в разделе Обновления в фоновом режиме, после развертывания и обновления приложения браузер получит обновленные файлы рабочей роли службы, чтобы запустить процесс обновления.

Что удивляет многих разработчиков, что, даже когда это обновление завершается, он не вступают в силу, пока пользователь не перейдет на все вкладки. Недостаточно обновить вкладку, отображающую приложение, даже если она является единственной вкладкой, отображающей приложение. Пока пользователь не закроет приложение полностью, новая рабочая роль службы будет оставаться в состоянии ожидания активации. Это не зависит Blazorот стандартного поведения веб-платформы.

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

Вкладка

Рабочая роль будет находиться в состоянии ожидания до тех пор, пока список "клиентов" (т. е. вкладок или окон, в которых отображается приложение) не опустеет. Это необходимо для обеспечения согласованности. Согласованность означает получение всех ресурсов из одного атомарного кэша.

При тестировании изменений может быть удобно выбрать ссылку skipWaiting, как показано на предыдущем снимке экрана, а затем перезагрузить страницу. Можно автоматизировать этот процесс для всех пользователей, реализовав в коде рабочей роли службы пропуск этапа "ожидания" с немедленной активацией обновления. Если пропустить этап ожидания, согласованное получение ресурсов из одного и того же экземпляра кэша не гарантируется.

Пользователи могут запускать любую ранее существовавшую версию приложения

Как правило, разработчики веб-приложения ожидают, что пользователи будут работать только с его последней развернутой версией, поскольку это характерно для традиционной модели распространения. Тем не менее прогрессивное веб-приложение с предпочтительным автономным режимом работы в этом отношении больше похоже на собственное мобильное приложение, пользователи которого далеко не всегда работают с последней версией.

Как описано в разделе "Фоновые обновления ", после развертывания обновления в приложении каждый существующий пользователь продолжает использовать предыдущую версию по крайней мере для одного дальнейшего посещения, так как обновление происходит в фоновом режиме и не активируется до тех пор, пока пользователь после этого не перейдет. Кроме того, в этом случае предыдущей используемой версией не обязательно будет та, которую вы развернули в прошлый раз. В зависимости от того, когда пользователь последний раз выполнял обновление, это может быть любая ранее существовавшая версия.

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

Соответственно, по возможности не следует развертывать существенные изменения в серверных API. Если это все же необходимо, рекомендуется использовать стандартные API рабочей роли службы, такие как ServiceWorkerRegistration, для определения актуальности версии приложения и блокировки его старых версий.

Возникают помехи в работе подготавливаемых к просмотру на сервере страниц

Как описывается выше в разделе Поддержка страниц, подготавливаемых к просмотру на сервере, чтобы обойти поведение рабочей роли службы и предотвратить возврат содержимого /index.html для всех запросов навигации, измените логику рабочей роли службы.

По умолчанию кэшируется все содержимое манифеста ресурса рабочей роли службы

Как описывается выше в разделе Управление кэшированием ресурсов, файл service-worker-assets.js создается в процессе сборки и содержит список всех ресурсов, которые должна получать и кэшировать рабочая роль службы.

Поскольку в этот список по умолчанию включается все содержимое, размещаемое в каталоге wwwroot, в том числе и поступающее из внешних пакетов и проектов, необходимо тщательно следить за тем, чтобы в этом каталоге не было слишком много содержимого. Если каталог wwwroot содержит несколько миллионов изображений, рабочая роль службы попытается получить и кэшировать их все, что приведет к перегрузке сети и, скорее всего, закончится сбоем.

Реализуйте произвольную логику, ограничивающую получение и кэширование содержимого манифеста, внеся соответствующие изменения в функцию onInstall в файле service-worker.published.js.

Взаимодействие с технологиями проверки подлинности

Шаблон PWA можно использовать вместе с проверкой подлинности. Прогрессивные веб-приложения с поддержкой автономной работы также могут обеспечивать проверку подлинности при наличии у пользователя начального подключения к сети.

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

Если приложение, предназначенное для работы в сети и в автономном режиме, снова подключено к сети:

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

Чтобы создать автономное приложение PWA, взаимодействующее с проверкой подлинности:

  • замените AccountClaimsPrincipalFactory<TAccount> фабрикой, которая хранит последнего пользователя, выполнившего вход, и использует сохраненного пользователя, когда приложение находится в автономном режиме;
  • поместите операции в очередь, пока приложение находится в автономном режиме, и примените их при переходе приложения в режим "в сети";
  • во время выхода очистите сохраненного пользователя.

Описанные выше подходы демонстрируются в примере приложения CarChecker. Ознакомьтесь со следующими частями приложения:

  • OfflineAccountClaimsPrincipalFactory (Client/Data/OfflineAccountClaimsPrincipalFactory.cs)
  • LocalVehiclesStore (Client/Data/LocalVehiclesStore.cs)
  • Компонент LoginStatus (Client/Shared/LoginStatus.razor)

Дополнительные ресурсы