当你在一个 TypeScript 项目中添加 PWA 模式(quasar mode add pwa)时,Quasar 会将 Service Worker 脚手架到 /src-pwa/sw/ 目录中,并配备独立的 tsconfig.json,使 WebWorker 上下文的类型检查独立于应用的其余部分。
/src-pwa/sw/tsconfig.json 是一个指向 .quasar/ 中生成配置的简洁引用:
{
"extends": "../../.quasar/tsconfig.pwa-sw.json"
}生成的 .quasar/tsconfig.pwa-sw.json 处理了 WebWorker lib 替换,并将 include/exclude 限定到 SW 目录。如需自定义,建议在 quasar.config.ts 中使用 pwa.extendPWASwTsConfig 钩子,而不是直接编辑 src-pwa/sw/tsconfig.json:
pwa: {
/**
* 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')
}
}register-sw.ts 保留在 /src-pwa/ 根目录,因为它在主线程中运行,会随 /src 一起通过 Vite 打包到应用中。/src-pwa/sw/ 内的所有内容则由 Rolldown 单独构建,运行在 Service Worker 上下文中。你可以在 sw/ 中添加更多仅用于 SW 的模块,并从 custom-sw.ts 中导入它们;主线程模块则直接放在 src-pwa/ 下,或从 /src 导入即可。
类型检查的工作原理
TypeScript 在从项目根目录运行 tsc/vue-tsc 时不会识别嵌套的 tsconfig.json 文件,它会将根编译器选项应用于 include 中的所有文件。为了避免 Service Worker 代码出现类型错误(例如在 DOM lib 下 ServiceWorkerGlobalScope.skipWaiting 不存在),Quasar CLI 在安装 PWA 模式时会在 .quasar/tsconfig.json > excludes 中添加 /src-pwa/sw/。
IDE 的语言服务器仍然会将 /src-pwa/sw/tsconfig.json 应用于该目录内的文件(TS 将嵌套的 tsconfig 视为独立项目),所以你依然能在那里获得正确的自动补全和内联诊断。
(ESLint) 在 dev/build 中对 Service Worker 进行类型检查
由于 SW 被排除在根项目之外,运行 vue-tsc 的 vite-plugin-checker 实例不会检查它。要在 quasar dev/quasar build 时获得内联的 SW 诊断信息,请在 quasar.config.ts 中为 vite-plugin-checker 配置添加一个 typescript 条目:
build: {
vitePlugins: [
[
'vite-plugin-checker',
{
vueTsc: true,
typescript: {
tsconfigPath: './src-pwa/sw/tsconfig.json'
}
// ...
},
{ server: false }
]
]
}在 package.json 中添加一个 typecheck 脚本也是常见做法:
{
"scripts": {
"typecheck": "vue-tsc --noEmit && tsc -p src-pwa/sw/tsconfig.json --noEmit"
}
}将现有 PWA 目录迁移到 TypeScript
如果你在项目还是 JavaScript 时添加了 PWA 模式,后来才切换到 TypeScript,/src-pwa/ 目录不会被重新脚手架。你需要手动转换:
- 重命名
/src-pwa/register-sw.js->/src-pwa/register-sw.ts。 - 创建
/src-pwa/sw/并将/src-pwa/custom-sw.js移动到/src-pwa/sw/custom-sw.ts(同时修改扩展名)。 - 创建
/src-pwa/sw/tsconfig.json,内容如上所示。 - 在
custom-sw.ts顶部添加 SW 类型声明(参见下方"默认 Service Worker 内容"),并进行其他 TS 相关的代码调整。 - (可选)按上述方式配置
vite-plugin-checker的typescript条目和/或添加typecheck脚本。
默认 Service Worker 内容
/*
* 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'
declare const self: ServiceWorkerGlobalScope & typeof globalThis
void 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$/
]
}
)
)
}