为什么捐赠
API 浏览器
升级指南
NEW!
创建新项目
quasar.config 配置文件
从 Webpack 项目转换
浏览器兼容性
TypeScript 支持
目录结构
命令列表
CSS 预处理器
使用 VueRouter 进行页面路由
懒加载 - 代码分割
资源处理
Boot 文件
预取特性
API 代理
配置 Vite
处理 import.meta.env
使用 Pinia 管理状态
代码检查与格式化
测试与审计
开发移动应用
Ajax 请求
开放开发服务器到公网
联系站长
Quasar CLI with Vite - @quasar/app-vite
配置 PWA

Service Worker

为 Quasar 项目添加 PWA 模式意味着会创建一个新目录:/src-pwa,其中包含 PWA 专属文件:

register-sw.js
# (或 .ts) 管理 Service Worker 的 UI 代码(主线程)
manifest.json
# PWA manifest 文件
package.json
# 用于在 /src-pwa 下直接安装 PWA 专属依赖
custom-sw.js
# (或 .ts) 可选的自定义 Service Worker 文件(仅 InjectManifest 模式)
tsconfig.json
# 仅 TypeScript - WebWorker lib,作用域限定在 /src-pwa/sw/

你可以自由编辑这些文件。注意以下几点:

  1. register-sw.js 会自动导入到你的应用中(和其他 /src 文件一样)。它注册 Service Worker(由 Workbox 创建或你的自定义 Worker,取决于 workbox 插件模式 – quasar.config file > pwa > workboxPluginMode),你可以监听 Service Worker 的事件。
  2. sw/custom-sw.js 仅在 workbox 插件模式设置为 “InjectManifest” 时才会作为你的 Service Worker 文件(quasar.config file > pwa > workboxMode: ‘InjectManifest’)。否则,Quasar 和 Workbox 会为你创建一个 Service Worker 文件。/src-pwa/sw/ 目录是 WebWorker 上下文,其中的所有代码都运行在 Service Worker 中,而非主线程。
  3. 建议仅在生产构建上运行 Lighthouse 测试。

TIP

处理 Service Worker 文档页面了解更多关于 register-sw.js 以及如何与 Service Worker 交互的内容。

quasar.config 文件

这里是你配置 Workbox 行为和调整 manifest.json 的地方。

pwa: {
  workboxMode?: "GenerateSW" | "InjectManifest";

  /**
   * Generated service worker filename to use (needs to end with .js)
   * @default sw.js
   */
  swFilename?: string;

  /**
   * PWA manifest filename to use on your browser
   * @default manifest.json
   */
  manifestFilename?: string;

  /**
   * Should you need some dynamic changes to the /src-pwa/manifest.json,
   * use this method to do it.
   */
  extendPWAManifestJson?: (json: PwaManifestOptions) => void;

  /**
   * Does the PWA manifest tag requires crossorigin auth?
   * @default false
   */
  useCredentialsForManifestTag?: boolean;

  /**
   * Auto inject the PWA meta tags?
   * If using the function form, return HTML tags as one single string.
   * @default true
   */
  injectPWAMetaTags?: boolean | ((injectParam: InjectPWAMetaTagsParams) => string);

  /**
   * Extend the Rolldown config that is used for the custom service worker
   * (if using it through workboxMode: 'InjectManifest').
   *
   * Can be async. Can directly modify the "config" parameter or
   * return a new one that will be merged with the default one.
   */
  extendPWACustomSWConf?: (
    config: RolldownOptions
  ) => void | RolldownOptions | Promise<void | RolldownOptions>;

  /**
   * Extend/configure the Workbox GenerateSW options.
   *
   * Can be async. Can directly modify the "config" parameter or
   * return a new one that will be merged with the default one.
   */
  extendPWAGenerateSWOptions?: (
    config: GenerateSWOptions
  ) => void | GenerateSWOptions | Promise<void | GenerateSWOptions>;

  /**
   * Extend/configure the Workbox InjectManifest options.
   *
   * Can be async. Can directly modify the "config" parameter or
   * return a new one that will be merged with the default one.
   */
  extendPWAInjectManifestOptions?: (
    config: InjectManifestOptions
  ) => void | InjectManifestOptions | Promise<void | InjectManifestOptions>;

  /**
   * Extend the generated `.quasar/tsconfig.pwa-sw.json` file.
   *
   * NOT async! Can directly modify the "config" parameter or
   * return a new one that will be merged with the default one.
   */
  extendPWASwTsConfig (tsConfig) {
    tsConfig.compilerOptions!.lib!.push('WebWorker.AsyncIterable')
  }
}

sourceFiles: {
  pwaRegisterServiceWorker: 'src-pwa/register-sw',
  pwaServiceWorker: 'src-pwa/sw/custom-sw',
  pwaManifestFile: 'src-pwa/manifest.json',
}

如果你想修改 /src 中 UI 的 Vite 配置:

/quasar.config file

export default defineConfig(ctx => {
  return {
    build: {
      extendViteConf(viteConf) {
        if (ctx.mode.pwa) {
          // do something with viteConf
          // or return an object to deeply merge with current viteConf
        }
      }
    }
  }
})

更多信息:Workbox

Adding your own meta tags in index.html

Quasar CLI 会动态地为你的 index.html 添加一些 PWA 相关的 meta 标签。如果你想自定义这些标签,首先在 /quasar.config 文件中禁用此行为:

/quasar.config file

pwa: {
  injectPWAMetaTags: false
}

然后编辑你的 /index.html 文件。以下是 Quasar CLI 动态注入的实际 meta 标签:

<head>
  <% if (ctx.mode.pwa) { %>
  <meta name="theme-color" content="<%= pwaManifest.theme_color %>" />
  <link
    rel="mask-icon"
    href="icons/safari-pinned-tab.svg"
    color="<%= pwaManifest.theme_color %>"
  />
  <meta name="mobile-web-app-capable" content="yes" />
  <meta name="apple-mobile-web-app-status-bar-style" content="default" />
  <meta name="msapplication-TileImage" content="icons/ms-icon-144x144.png" />
  <meta name="msapplication-TileColor" content="#000000" />
  <meta name="apple-mobile-web-app-title" content="<%= pwaManifest.name %>" />
  <link rel="apple-touch-icon" href="icons/apple-icon-120x120.png" />
  <link
    rel="apple-touch-icon"
    sizes="152x152"
    href="icons/apple-icon-152x152.png"
  />
  <link
    rel="apple-touch-icon"
    sizes="167x167"
    href="icons/apple-icon-167x167.png"
  />
  <link
    rel="apple-touch-icon"
    sizes="180x180"
    href="icons/apple-icon-180x180.png"
  />
  <% } %>
</head>

注意你可以通过上面的 pwaManifest 访问你的 PWA manifest。

或者,你可以像下面这样给 injectPWAMetaTags 赋值一个函数:

/quasar.config file

pwa: {
  injectPWAMetaTags ({ pwaManifest, publicPath }) {
    return `<meta name="mobile-web-app-capable" content="yes">`
      + `<meta name="apple-mobile-web-app-status-bar-style" content="default">`
  }
}

Picking Workbox mode

Workbox 有两种工作模式:GenerateSW(默认)和 InjectManifest

通过 /quasar.config 文件设置你想使用的模式:

/quasar.config file

pwa: {
  workboxMode: 'GenerateSW',
  extendPWAGenerateSWOptions (cfg) {
    // configure workbox on GenerateSW
  }
}

pwa: {
  workboxMode: 'InjectManifest',
  extendPWAInjectManifestOptions (cfg) {
    // configure workbox on InjectManifest
  }
}

GenerateSW

何时使用 GenerateSW:

  • You want to precache files.
  • You have simple runtime configuration needs (e.g. the configuration allows you to define routes and strategies).

何时不使用 GenerateSW:

  • You want to use other Service Worker features (i.e. Web Push).
  • You want to import additional scripts or add additional logic.

TIP

请查看 Workbox 网站 上此模式可用的 workboxOptions。

InjectManifest

何时使用 InjectManifest:

  • You want more control over your service worker.
  • You want to precache files.
  • You have more complex needs in terms of routing.
  • You would like to use your service worker with other APIs (e.g. Web Push).

何时不使用 InjectManifest:

  • You want the easiest path to adding a service worker to your site.

TIPS

  • If you want to use this mode, you will have to write the service worker (/src-pwa/sw/custom-sw.js) file by yourself.
  • Please check the available workboxOptions for this mode on Workbox website.

以下代码片段是自定义 Service Worker(/src-pwa/sw/custom-sw.js)的默认代码,它模拟了 generateSW 模式的行为:

/src-pwa/sw/custom-sw file

/*
 * This file (which will be your service worker)
 * is picked up by the build system ONLY if
 * quasar.config file > pwa > workboxMode is set to "InjectManifest"
 */

import { clientsClaim } from 'workbox-core'
import { NavigationRoute, registerRoute } from 'workbox-routing'
import {
  cleanupOutdatedCaches,
  createHandlerBoundToURL,
  precacheAndRoute
} from 'workbox-precaching'

self.skipWaiting()
clientsClaim()

// Use with precache injection
precacheAndRoute(self.__WB_MANIFEST)

cleanupOutdatedCaches()

if (import.meta.env.QUASAR_PROD) {
  // Non-SSR fallbacks to index.html
  // Production SSR fallbacks to offline.html (except for dev)
  registerRoute(
    new NavigationRoute(
      createHandlerBoundToURL(import.meta.env.QUASAR_PWA_FALLBACK_HTML),
      {
        denylist: [
          new RegExp(import.meta.env.QUASAR_PWA_SERVICE_WORKER_REGEX),
          /workbox-(.)*\.js$/
        ]
      }
    )
  )
}

Configuring Manifest File

Manifest 文件位于 /src-pwa/manifest.json,你可以自由编辑它。

如果你需要在构建时动态修改它,可以编辑 /quasar.config 文件:

/quasar.config file

pwa: {
  extendPWAManifestJson (json) {
    // tamper with the json inline
  }
}

在深入之前请先阅读 manifest 配置

WARNING

注意你不需要编辑 index.html 文件(从 /index.html 生成)来链接 manifest 文件。Quasar CLI 会为你处理好一切。

TIP

如果你的 PWA 在基本认证后面或需要 Authorization 头,请将 quasar.config file > pwa > useCredentialsForManifestTag 设置为 true,以在 manifest.json meta 标签上包含 crossorigin="use-credentials"

PWA Checklist

更多信息:PWA 检查清单

WARNING

Do not run Lighthouse on your development build because at this stage the code is intentionally not optimized and contains embedded source maps (among many other things). See the Testing and Auditing section of these docs for more information.

Reload & Update Automatically

For those who don’t want to manually reload the page when the service worker is updated and are using the default generateSW workbox mode, Quasar CLI has configured Workbox to activate it at once. Should you need to disable this behavior:

/quasar.config file

pwa: {
  extendPWAGenerateSWOptions (cfg) {
    cfg.skipWaiting = false
    cfg.clientsClaim = false
  }
}

Filename hashes quirk

Due to how Rolldown builds the assets (through Vite), when you change any of your script source files (.js) this will also change the hash part of (almost) ALL .js files (ex: 454d87bd in assets/index.454d87bd.js). The revision number of all assets will get changed in your service worker file and this means that when PWA updates it will re-download ALL your assets again. What a waste of bandwidth and such a longer time to get the PWA updated!

By default, Vite builds all filenames with the hash part. However, should you want your filenames to NOT contain the hash part, you need to edit the /quasar.config file:

/quasar.config file

build: {
  useFilenameHashes: false // true by default
}

When filename hashes are disabled it would be wise to also make sure that your webserver has cache set accordingly (as low as possible) to ensure consistent resource delivery to your clients that can’t use the PWA functionality.