项目

PWA 配置

渐进式Web应用(PWA)是使用特定技术开发的,允许应用程序同时利用Web和原生应用的功能。

以下是PWA提供的一些功能列表:

  • 可安装:Web应用程序可以像原生/桌面应用程序一样安装和使用。
  • 网络独立:PWA支持离线场景。它可以在离线或网络连接不佳的情况下工作。
  • 响应式:可在任何设备上使用,如手机、平板电脑、笔记本电脑等。

创建支持PWA的项目

您可以使用 --pwa 选项为 Blazor WebAssembly 创建一个支持PWA的新Web应用程序,如下所示:

abp new Acme.BookStore -t blazor --pwa

执行此命令后,您的应用程序将被创建,并且会添加一些与PWA相关的附加文件(例如 manifest图标服务工作者 等)。然后,您就可以充分利用Web和原生应用功能的所有优势。

向现有项目添加PWA支持

如果您最初创建应用程序时没有PWA支持,之后仍然可以改变主意并享受PWA的好处。您只需要按照以下列表进行一些配置:

1-) 添加 manifest.json 文件

Web应用程序清单通过JSON文本文件提供有关Web应用程序的信息,这是Web应用程序能够像原生应用程序一样被下载和呈现给用户所必需的。

首先,您需要在 wwwroot 文件夹下创建一个名为 manifest.json 的JSON文件,并定义有关您应用程序的一些信息。您可以在下面看到一个示例 manifest.json 文件内容:

{
  "name": "MyProjectName",
  "short_name": "MyCompanyName.MyProjectName",
  "start_url": "./",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#03173d",
  "prefer_related_applications": false,
  "icons": [
    {
      "src": "icon-512.png",
      "type": "image/png",
      "sizes": "512x512"
    },
    {
      "src": "icon-192.png",
      "type": "image/png",
      "sizes": "192x192"
    }
  ]
}
  • 应在此文件中定义一些应用程序特定的信息。
  • 例如,您可以配置在哪些屏幕尺寸下显示哪个图标、背景颜色、描述等。

2-) 为特定屏幕尺寸添加图标(可选)

您可以为您应用程序添加一些图标,以便在特定屏幕尺寸下显示,并在 manifest.json 文件中定义应在哪些屏幕尺寸下显示图标。您可以在上面的示例中看到 manifest.json 文件中的 icons 部分。

您可以使用我们模板中的默认图标。

3-) 配置服务工作者

服务工作者是PWA的基本组成部分之一。它们支持快速加载(无论网络状况如何)、离线访问、推送通知以及其他Web/原生应用功能。它们在后台运行,不会阻塞主线程,因此不会降低您的应用程序速度。

您需要在项目的 wwwroot 文件夹下创建 service-worker.jsservice-worker.published.js 文件。这些文件将被您的项目用来确定您想要使用的PWA功能。

您可以从我们的模板中获取 service-worker.jsservice-worker.published.js 文件的简单配置。

添加相关的服务工作者文件后,我们需要在我们的 .csproj 文件中定义它们以通知我们的应用程序。因此,请打开您的 *.csproj 文件并添加以下内容:

<PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>

    <!-- 添加以下行 -->
    <ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
</PropertyGroup>

<!-- 添加以下项目组 -->
<ItemGroup>
    <ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" />
</ItemGroup>
  • 通过 ServiceWorkerAssetsManifest MSBuild属性,您的Blazor应用程序会生成一个具有指定名称的服务工作者资源清单。该文件将在运行时生成在 /bin/Debug/{TARGET FRAMEWORK}/wwwroot/service-worker-assets.js 路径下。该清单可以通过检查 service-worker.published.js 文件(根据您在此文件中的配置)列出所有资源,如图像、样式表、JS文件等。
  • ServiceWorker 属性用于定义哪些文件需要被视为服务工作者文件,服务工作者用于确定应使用哪些PWA功能。

4-) 定义Web应用程序清单并注册服务工作者

最后,现在您可以在 index.html 文件中定义 manifest.json 文件和图标,并为您的应用程序注册服务工作者

首先,在 index.html 文件(位于 wwwroot 文件夹下)的 <head> 标签之间添加清单和应用程序图标的 <link> 元素:

<head>
  <!-- ... -->  
  <link href="manifest.json" rel="manifest" />
  <link rel="apple-touch-icon" sizes="512x512" href="icon-512.png" />
  <link rel="apple-touch-icon" sizes="192x192" href="icon-192.png" />
</head>

然后,在同一文件的闭合 </body> 标签内添加以下 <script> 标签:

<body>
  <!-- ... --> 
  <script>
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.register("service-worker.js");
    }
  </script>
</body>

通过这最后一步,您已经添加了相关文件并完成了相关配置,为您现有的应用程序添加了PWA支持。现在,您可以充分利用PWA的所有优势。

调试版和发布版服务工作者的区别

如果您创建带有PWA支持的应用程序,应用程序模板会生成两个服务工作者文件:

  • service-worker.js 文件在开发期间使用,默认情况下不执行任何操作。
  • service-worker.published.js 文件,在应用程序发布后使用。默认情况下会缓存某些文件扩展名并支持离线场景(使用缓存优先策略)。用户必须首先在线时访问应用程序。浏览器会自动下载并缓存离线操作所需的所有资源,然后当网络连接断开时,它可以像之前一样使用。

您可以按照下面“自定义服务工作者”部分所述配置这些文件。

如果您想在这两个服务工作者文件之间共享逻辑,可以考虑创建第三个JS文件,并将公共逻辑放在此文件中,或使用 self.importScripts 将公共逻辑加载到两个服务工作者文件中。

自定义

如果您创建的应用程序支持PWA,您可以自定义ABP生成的 manifest.jsonservice-worker.jsservice-worker.published.js 文件。

自定义Web应用程序清单 (manifest.json)

Web应用程序清单是一个JSON文件,它告诉浏览器有关您的渐进式Web应用的信息,以及当它安装在用户的桌面或移动设备上时应如何表现。典型的清单文件包括应用程序名称、应用程序应使用的图标以及启动应用程序时应打开的URL。- 来自 web.dev

您可以根据需要自定义 manifest.json 文件(位于 wwwroot 文件夹下)。您可以设置 nameshort_nameiconsdescriptionstart_url 等。您可以在下面看到一个示例 manifest.json 文件内容:

{
  "name": "Acme.BookStore",
  "short_name": "BookStore",
  "description": "我的应用程序描述",
  "theme_color": "#000000",
  "background_color": "#ffffff",
  "icons": [
    {
      "src": "../icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "../icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
  // 其他属性...
}
  • 您必须至少提供 short_namename 属性。如果同时提供了这两个属性,启动器屏幕等几乎所有地方都会使用 short_name 属性。
  • 对于基于Chromium的浏览器,您必须至少提供一个 192x192 像素的图标和一个 512x512 像素的图标。如果只提供了这两种图标尺寸,浏览器将自动缩放图标以适应设备。如果您不希望浏览器自动缩放图标,则需要添加其他尺寸的图标。

您可以从这里查看其他属性。

自定义服务工作者

如果您创建带有PWA支持的应用程序,将生成两个服务工作者文件:service-worker.jsservice-worker.published.js

ABP的服务工作者文件与.NET Core的相同,并且在大多数情况下都适用,您可能不需要手动配置它。但是,如果您想配置服务工作者,可以轻松完成。

您可以根据自己的需求配置 service-worker.js 文件(用于调试模式)和 service-worker.published.js 文件(用于发布模式)。

service-worker.js

// 注意:在开发过程中,始终从网络获取,并且不启用离线支持。
self.addEventListener('fetch', () => { });
  • 通过配置此文件,您可以在调试模式下使用额外的PWA功能。
  • 默认情况下,它在调试模式下不执行任何操作,从网络获取(推荐)并且不支持离线场景。您可以通过配置此文件来更改此行为,并享受PWA的额外功能。

service-worker.published.js

// 注意:在发布支持离线功能的应用程序之前,请务必了解其中的注意事项。参见 https://aka.ms/blazor-offline-considerations

self.importScripts('./service-worker-assets.js');
self.addEventListener('install', event => event.waitUntil(onInstall(event)));
self.addEventListener('activate', event => event.waitUntil(onActivate(event)));
self.addEventListener('fetch', event => event.respondWith(onFetch(event)));

const cacheNamePrefix = 'offline-cache-';
const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`;
const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/ ];
const offlineAssetsExclude = [ /^service-worker\.js$/ ];

async function onInstall(event) {
    console.info('Service worker: 安装');

    // 从资源清单中获取并缓存所有匹配的项目
    const assetsRequests = self.assetsManifest.assets
        .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
        .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
        .map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' }));
    await caches.open(cacheName).then(cache => cache.addAll(assetsRequests));
}

async function onActivate(event) {
    console.info('Service worker: 激活');

    // 删除未使用的缓存
    const cacheKeys = await caches.keys();
    await Promise.all(cacheKeys
        .filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName)
        .map(key => caches.delete(key)));
}

async function onFetch(event) {
    let cachedResponse = null;
    if (event.request.method === 'GET') {
        // 对于所有导航请求,尝试从缓存中提供 index.html
        // 如果您需要某些URL由服务器渲染,请编辑以下检查以排除这些URL
        const shouldServeIndexHtml = event.request.mode === 'navigate';

        const request = shouldServeIndexHtml ? 'index.html' : event.request;
        const cache = await caches.open(cacheName);
        cachedResponse = await cache.match(request);
    }

    return cachedResponse || fetch(event.request);
}
  • 如果您想缓存额外的文件扩展名,例如 .webp 等,可以配置此文件。您还可以通过配置此文件来使用PWA的一些额外功能。
  • 默认情况下,dll文件(*.dll)和一些静态资源(*.js*.css 等)会被缓存。
  • 缓存的文件将存储在 service-worker-assets.js/bin/Debug//wwwroot/service-worker-assets.js)中。您可以通过在 *.csproj 文件中的 ServiceWorkerAssetsManifest 标签之间重命名来更改此文件名。

另请参阅

在本文档中