@vite-pwa/nuxt 1.1.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -59
- package/config/index.d.mts +1 -0
- package/config/index.mjs +3 -0
- package/configuration.d.ts +3 -0
- package/dist/chunks/create-nuxt-pwa-context.mjs +27 -0
- package/dist/chunks/prepare-module.mjs +871 -0
- package/dist/chunks/prepare-pwa-icons.mjs +161 -0
- package/dist/module.d.mts +42 -89
- package/dist/module.json +4 -4
- package/dist/module.mjs +40 -8
- package/dist/runtime/components/NuxtPwaAssets.d.ts +1 -1
- package/dist/runtime/components/NuxtPwaAssets.js +8 -4
- package/dist/runtime/components/{VitePwaManifest.d.ts → NuxtPwaManifest.d.ts} +1 -1
- package/dist/runtime/components/{VitePwaManifest.js → NuxtPwaManifest.js} +2 -2
- package/dist/runtime/{composables/index.d.ts → composables.d.ts} +12 -28
- package/dist/runtime/{composables/index.js → composables.js} +1 -11
- package/dist/runtime/plugins/pwa-install.client.d.ts +6 -0
- package/dist/runtime/plugins/pwa-install.client.js +70 -0
- package/dist/runtime/plugins/pwa.client.d.ts +1 -1
- package/dist/runtime/plugins/pwa.client.js +90 -77
- package/dist/runtime/plugins/types.d.ts +70 -129
- package/dist/runtime/plugins/types.js +0 -0
- package/dist/types.d.mts +5 -5
- package/package.json +40 -59
- package/dist/chunks/dev.mjs +0 -37
- package/dist/chunks/pwa-icons.mjs +0 -155
- package/dist/module.cjs +0 -5
- package/dist/module.d.ts +0 -110
- package/dist/runtime/components/PwaAppleImage.vue +0 -12
- package/dist/runtime/components/PwaAppleImage.vue.d.ts +0 -2
- package/dist/runtime/components/PwaAppleSplashScreenImage.vue +0 -12
- package/dist/runtime/components/PwaAppleSplashScreenImage.vue.d.ts +0 -2
- package/dist/runtime/components/PwaFaviconImage.vue +0 -12
- package/dist/runtime/components/PwaFaviconImage.vue.d.ts +0 -2
- package/dist/runtime/components/PwaMaskableImage.vue +0 -12
- package/dist/runtime/components/PwaMaskableImage.vue.d.ts +0 -2
- package/dist/runtime/components/PwaTransparentImage.vue +0 -12
- package/dist/runtime/components/PwaTransparentImage.vue.d.ts +0 -2
- package/dist/runtime/components/nuxt4/PwaAppleImage.d.ts +0 -4
- package/dist/runtime/components/nuxt4/PwaAppleImage.js +0 -15
- package/dist/runtime/components/nuxt4/PwaAppleSplashScreenImage.d.ts +0 -4
- package/dist/runtime/components/nuxt4/PwaAppleSplashScreenImage.js +0 -15
- package/dist/runtime/components/nuxt4/PwaFaviconImage.d.ts +0 -4
- package/dist/runtime/components/nuxt4/PwaFaviconImage.js +0 -15
- package/dist/runtime/components/nuxt4/PwaMaskableImage.d.ts +0 -4
- package/dist/runtime/components/nuxt4/PwaMaskableImage.js +0 -15
- package/dist/runtime/components/nuxt4/PwaTransparentImage.d.ts +0 -4
- package/dist/runtime/components/nuxt4/PwaTransparentImage.js +0 -15
- package/dist/shared/nuxt.9518178d.mjs +0 -734
- package/dist/types.d.ts +0 -15
|
@@ -1,734 +0,0 @@
|
|
|
1
|
-
import { addPluginTemplate, addTypeTemplate, addImports, createResolver, getNuxtVersion, resolveAlias, addPlugin, addComponent, extendWebpackConfig, addDevServerHandler, defineNuxtModule } from '@nuxt/kit';
|
|
2
|
-
import { lstat, writeFile, mkdir } from 'node:fs/promises';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { VitePWA } from 'vite-plugin-pwa';
|
|
5
|
-
import { createHash } from 'node:crypto';
|
|
6
|
-
import { createReadStream } from 'node:fs';
|
|
7
|
-
import { resolve } from 'pathe';
|
|
8
|
-
|
|
9
|
-
const version = "1.1.1";
|
|
10
|
-
|
|
11
|
-
function configurePWAOptions(ctx, nitroConfig) {
|
|
12
|
-
const { nuxt3_8, options, nuxt } = ctx;
|
|
13
|
-
if (!options.outDir) {
|
|
14
|
-
const publicDir = nitroConfig.output?.publicDir ?? nuxt.options.nitro?.output?.publicDir;
|
|
15
|
-
options.outDir = publicDir ? resolve(publicDir) : resolve(nuxt.options.buildDir, "../.output/public");
|
|
16
|
-
}
|
|
17
|
-
if (options.devOptions?.enabled)
|
|
18
|
-
options.devOptions.resolveTempFolder = () => resolve(nuxt.options.buildDir, "dev-sw-dist");
|
|
19
|
-
let config;
|
|
20
|
-
if (options.strategies === "injectManifest") {
|
|
21
|
-
options.injectManifest = options.injectManifest ?? {};
|
|
22
|
-
config = options.injectManifest;
|
|
23
|
-
} else {
|
|
24
|
-
options.strategies = "generateSW";
|
|
25
|
-
options.workbox = options.workbox ?? {};
|
|
26
|
-
if (options.registerType === "autoUpdate" && (options.client?.registerPlugin || options.injectRegister === "script" || options.injectRegister === "inline")) {
|
|
27
|
-
options.workbox.clientsClaim = true;
|
|
28
|
-
options.workbox.skipWaiting = true;
|
|
29
|
-
}
|
|
30
|
-
if (nuxt.options.dev) {
|
|
31
|
-
options.workbox.navigateFallback = options.workbox.navigateFallback ?? nuxt.options.app.baseURL ?? "/";
|
|
32
|
-
if (options.devOptions?.enabled && !options.devOptions.navigateFallbackAllowlist) {
|
|
33
|
-
const baseURL = nuxt.options.app.baseURL;
|
|
34
|
-
options.devOptions.navigateFallbackAllowlist = [baseURL ? new RegExp(`^${baseURL.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&")}$`) : /^\/$/];
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
if (!("navigateFallback" in options.workbox))
|
|
38
|
-
options.workbox.navigateFallback = nuxt.options.app.baseURL ?? "/";
|
|
39
|
-
config = options.workbox;
|
|
40
|
-
}
|
|
41
|
-
let buildAssetsDir = nuxt.options.app.buildAssetsDir ?? "_nuxt/";
|
|
42
|
-
if (buildAssetsDir[0] === "/")
|
|
43
|
-
buildAssetsDir = buildAssetsDir.slice(1);
|
|
44
|
-
if (buildAssetsDir[buildAssetsDir.length - 1] !== "/")
|
|
45
|
-
buildAssetsDir += "/";
|
|
46
|
-
if (!("dontCacheBustURLsMatching" in config))
|
|
47
|
-
config.dontCacheBustURLsMatching = new RegExp(buildAssetsDir);
|
|
48
|
-
if (nuxt.options.experimental.payloadExtraction) {
|
|
49
|
-
const enableGlobPatterns = nuxt.options.nitro.static || nuxt.options._generate || (!!nitroConfig.prerender?.routes?.length || Object.values(nitroConfig.routeRules ?? {}).some((r) => r.prerender));
|
|
50
|
-
if (enableGlobPatterns) {
|
|
51
|
-
config.globPatterns = config.globPatterns ?? [];
|
|
52
|
-
config.globPatterns.push("**/_payload.json");
|
|
53
|
-
if (options.strategies === "generateSW" && options.experimental?.enableWorkboxPayloadQueryParams) {
|
|
54
|
-
options.workbox.runtimeCaching = options.workbox.runtimeCaching ?? [];
|
|
55
|
-
options.workbox.runtimeCaching.push({
|
|
56
|
-
urlPattern: /\/_payload\.json\?/,
|
|
57
|
-
handler: "NetworkOnly",
|
|
58
|
-
options: {
|
|
59
|
-
plugins: [{
|
|
60
|
-
/* this callback will be called when the fetch call fails */
|
|
61
|
-
handlerDidError: async ({ request }) => {
|
|
62
|
-
const url = new URL(request.url);
|
|
63
|
-
url.search = "";
|
|
64
|
-
return Response.redirect(url.href, 302);
|
|
65
|
-
},
|
|
66
|
-
/* this callback will prevent caching the response */
|
|
67
|
-
cacheWillUpdate: async () => null
|
|
68
|
-
}]
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
let appManifestFolder;
|
|
75
|
-
if (nuxt3_8 && nuxt.options.experimental.appManifest) {
|
|
76
|
-
config.globPatterns = config.globPatterns ?? [];
|
|
77
|
-
appManifestFolder = `${buildAssetsDir}builds/`;
|
|
78
|
-
config.globPatterns.push(`${appManifestFolder}**/*.json`);
|
|
79
|
-
}
|
|
80
|
-
if (!nuxt.options.dev && !config.manifestTransforms)
|
|
81
|
-
config.manifestTransforms = [createManifestTransform(nuxt.options.app.baseURL ?? "/", options.outDir, appManifestFolder)];
|
|
82
|
-
if (options.pwaAssets) {
|
|
83
|
-
options.pwaAssets.integration = {
|
|
84
|
-
baseUrl: nuxt.options.app.baseURL ?? "/",
|
|
85
|
-
publicDir: ctx.publicDirFolder,
|
|
86
|
-
outDir: options.outDir
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
const integration = options.integration ?? {};
|
|
90
|
-
const {
|
|
91
|
-
beforeBuildServiceWorker: original,
|
|
92
|
-
...rest
|
|
93
|
-
} = integration;
|
|
94
|
-
options.integration = {
|
|
95
|
-
...rest,
|
|
96
|
-
async beforeBuildServiceWorker(resolvedPwaOptions) {
|
|
97
|
-
await original?.(resolvedPwaOptions);
|
|
98
|
-
await nuxt.callHook("pwa:beforeBuildServiceWorker", resolvedPwaOptions);
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
function createManifestTransform(base, publicFolder, appManifestFolder) {
|
|
103
|
-
return async (entries) => {
|
|
104
|
-
entries.filter((e) => e.url.endsWith(".html")).forEach((e) => {
|
|
105
|
-
const url = e.url.startsWith("/") ? e.url.slice(1) : e.url;
|
|
106
|
-
if (url === "index.html") {
|
|
107
|
-
e.url = base;
|
|
108
|
-
} else {
|
|
109
|
-
const parts = url.split("/");
|
|
110
|
-
parts[parts.length - 1] = parts[parts.length - 1].replace(/\.html$/, "");
|
|
111
|
-
e.url = parts.length > 1 ? parts.slice(0, parts.length - 1).join("/") : parts[0];
|
|
112
|
-
}
|
|
113
|
-
});
|
|
114
|
-
if (appManifestFolder) {
|
|
115
|
-
const regExp = /(\/)?[0-9a-f]{8}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{4}\b-[0-9a-f]{12}\.json$/i;
|
|
116
|
-
entries.filter((e) => e.url.startsWith(appManifestFolder) && regExp.test(e.url)).forEach((e) => {
|
|
117
|
-
e.revision = null;
|
|
118
|
-
});
|
|
119
|
-
const latest = `${appManifestFolder}latest.json`;
|
|
120
|
-
const latestJson = resolve(publicFolder, latest);
|
|
121
|
-
const data = await lstat(latestJson).catch(() => void 0);
|
|
122
|
-
if (data?.isFile()) {
|
|
123
|
-
const revision = await new Promise((resolve2, reject) => {
|
|
124
|
-
const cHash = createHash("MD5");
|
|
125
|
-
const stream = createReadStream(latestJson);
|
|
126
|
-
stream.on("error", (err) => {
|
|
127
|
-
reject(err);
|
|
128
|
-
});
|
|
129
|
-
stream.on("data", (chunk) => cHash.update(chunk));
|
|
130
|
-
stream.on("end", () => {
|
|
131
|
-
resolve2(cHash.digest("hex"));
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
const latestEntry = entries.find((e) => e.url === latest);
|
|
135
|
-
if (latestEntry)
|
|
136
|
-
latestEntry.revision = revision;
|
|
137
|
-
else
|
|
138
|
-
entries.push({ url: latest, revision, size: data.size });
|
|
139
|
-
} else {
|
|
140
|
-
entries = entries.filter((e) => e.url !== latest);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return { manifest: entries, warnings: [] };
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function addPwaTypeTemplate(filename, isNuxt4, content) {
|
|
148
|
-
if (content?.length) {
|
|
149
|
-
return addTypeTemplate({
|
|
150
|
-
write: true,
|
|
151
|
-
filename: `pwa-icons/${filename}.d.ts`,
|
|
152
|
-
getContents: () => content
|
|
153
|
-
}).dst;
|
|
154
|
-
} else {
|
|
155
|
-
return addTypeTemplate({
|
|
156
|
-
write: true,
|
|
157
|
-
getContents: () => generatePwaImageType(filename, isNuxt4),
|
|
158
|
-
filename: `pwa-icons/${filename}.d.ts`
|
|
159
|
-
}).dst;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
function pwaIcons(types) {
|
|
163
|
-
return `// Generated by @vite-pwa/nuxt
|
|
164
|
-
import type { AppleSplashScreenLink, FaviconLink, HtmlLink, IconAsset } from '@vite-pwa/assets-generator/api'
|
|
165
|
-
|
|
166
|
-
export interface PWAAssetIconImage {
|
|
167
|
-
width?: number
|
|
168
|
-
height?: number
|
|
169
|
-
key: string
|
|
170
|
-
src: string
|
|
171
|
-
}
|
|
172
|
-
export type PWAAssetIcon<T extends HtmlLink> = Omit<IconAsset<T>, 'buffer'> & {
|
|
173
|
-
asImage: PWAAssetIconImage
|
|
174
|
-
}
|
|
175
|
-
export interface PWAIcons {
|
|
176
|
-
transparent: Record<${generateTypes(types?.transparent)}, PWAAssetIcon<HtmlLink>>
|
|
177
|
-
maskable: Record<${generateTypes(types?.maskable)}, PWAAssetIcon<HtmlLink>>
|
|
178
|
-
favicon: Record<${generateTypes(types?.favicon)}, PWAAssetIcon<FaviconLink>>
|
|
179
|
-
apple: Record<${generateTypes(types?.apple)}, PWAAssetIcon<HtmlLink>>
|
|
180
|
-
appleSplashScreen: Record<${generateTypes(types?.appleSplashScreen)}, PWAAssetIcon<AppleSplashScreenLink>>
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
declare module '#app' {
|
|
184
|
-
interface NuxtApp {
|
|
185
|
-
$pwaIcons?: PWAIcons
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
declare module 'vue' {
|
|
190
|
-
interface ComponentCustomProperties {
|
|
191
|
-
$pwaIcons?: PWAIcons
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
export {}
|
|
196
|
-
`;
|
|
197
|
-
}
|
|
198
|
-
function generatePwaImageType(filename, isNuxt4, names) {
|
|
199
|
-
const propsName = `${filename}Props`;
|
|
200
|
-
if (isNuxt4) {
|
|
201
|
-
return `// Generated by @vite-pwa/nuxt
|
|
202
|
-
export interface ${propsName} {
|
|
203
|
-
image: ${generateTypes(names)}
|
|
204
|
-
alt?: string
|
|
205
|
-
width?: number
|
|
206
|
-
height?: number
|
|
207
|
-
crossorigin?: '' | 'anonymous' | 'use-credentials'
|
|
208
|
-
loading?: 'lazy' | 'eager'
|
|
209
|
-
decoding?: 'async' | 'auto' | 'sync'
|
|
210
|
-
nonce?: string
|
|
211
|
-
}
|
|
212
|
-
`;
|
|
213
|
-
}
|
|
214
|
-
return `// Generated by @vite-pwa/nuxt
|
|
215
|
-
export interface ${propsName} {
|
|
216
|
-
image: ${generateTypes(names)}
|
|
217
|
-
alt?: string
|
|
218
|
-
width?: number
|
|
219
|
-
height?: number
|
|
220
|
-
crossorigin?: '' | 'anonymous' | 'use-credentials'
|
|
221
|
-
loading?: 'lazy' | 'eager'
|
|
222
|
-
decoding?: 'async' | 'auto' | 'sync'
|
|
223
|
-
nonce?: string
|
|
224
|
-
}
|
|
225
|
-
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T
|
|
226
|
-
type __VLS_TypePropsToRuntimeProps<T> = {
|
|
227
|
-
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
|
228
|
-
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>
|
|
229
|
-
} : {
|
|
230
|
-
type: import('vue').PropType<T[K]>
|
|
231
|
-
required: true
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
declare const _default: import('vue').DefineComponent<__VLS_TypePropsToRuntimeProps<${propsName}>, {}, unknown, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<__VLS_TypePropsToRuntimeProps<${propsName}>>>, {}, {}>
|
|
235
|
-
export default _default
|
|
236
|
-
`;
|
|
237
|
-
}
|
|
238
|
-
function generateTypes(types) {
|
|
239
|
-
return types?.length ? types.map((name) => `'${name}'`).join(" | ") : "string";
|
|
240
|
-
}
|
|
241
|
-
function addPWAIconsPluginTemplate(pwaAssetsEnabled) {
|
|
242
|
-
if (pwaAssetsEnabled) {
|
|
243
|
-
addPluginTemplate({
|
|
244
|
-
filename: "pwa-icons-plugin.ts",
|
|
245
|
-
name: "vite-pwa:nuxt:pwa-icons-plugin",
|
|
246
|
-
write: true,
|
|
247
|
-
getContents: () => `// Generated by @vite-pwa/nuxt
|
|
248
|
-
import { defineNuxtPlugin } from '#imports'
|
|
249
|
-
import { pwaAssetsIcons } from 'virtual:pwa-assets/icons'
|
|
250
|
-
import type { PWAAssetIcon, PWAIcons } from '#build/pwa-icons/pwa-icons'
|
|
251
|
-
|
|
252
|
-
export default defineNuxtPlugin(() => {
|
|
253
|
-
return {
|
|
254
|
-
provide: {
|
|
255
|
-
pwaIcons: {
|
|
256
|
-
transparent: configureEntry('transparent'),
|
|
257
|
-
maskable: configureEntry('maskable'),
|
|
258
|
-
favicon: configureEntry('favicon'),
|
|
259
|
-
apple: configureEntry('apple'),
|
|
260
|
-
appleSplashScreen: configureEntry('appleSplashScreen')
|
|
261
|
-
} satisfies PWAIcons
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
})
|
|
265
|
-
|
|
266
|
-
function configureEntry<K extends keyof PWAIcons>(key: K) {
|
|
267
|
-
return Object.values(pwaAssetsIcons[key] ?? {}).reduce((acc, icon) => {
|
|
268
|
-
const entry: PWAAssetIcon<any> = {
|
|
269
|
-
...icon,
|
|
270
|
-
asImage: {
|
|
271
|
-
src: icon.url,
|
|
272
|
-
key: \`\${key}-\${icon.name}\`
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
if (icon.width && icon.height) {
|
|
276
|
-
entry.asImage.width = icon.width
|
|
277
|
-
entry.asImage.height = icon.height
|
|
278
|
-
}
|
|
279
|
-
;(acc as unknown as any)[icon.name] = entry
|
|
280
|
-
return acc
|
|
281
|
-
}, {} as PWAIcons[typeof key])
|
|
282
|
-
}
|
|
283
|
-
`
|
|
284
|
-
});
|
|
285
|
-
} else {
|
|
286
|
-
addPluginTemplate({
|
|
287
|
-
filename: "pwa-icons-plugin.ts",
|
|
288
|
-
name: "vite-pwa:nuxt:pwa-icons-plugin",
|
|
289
|
-
write: true,
|
|
290
|
-
getContents: () => `// Generated by @vite-pwa/nuxt
|
|
291
|
-
import { defineNuxtPlugin } from '#imports'
|
|
292
|
-
import type { PWAIcons } from '#build/pwa-icons/pwa-icons'
|
|
293
|
-
|
|
294
|
-
export default defineNuxtPlugin(() => {
|
|
295
|
-
return {
|
|
296
|
-
provide: {
|
|
297
|
-
pwaIcons: {
|
|
298
|
-
transparent: {},
|
|
299
|
-
maskable: {},
|
|
300
|
-
favicon: {},
|
|
301
|
-
apple: {},
|
|
302
|
-
appleSplashScreen: {}
|
|
303
|
-
} satisfies PWAIcons
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
})
|
|
307
|
-
`
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
async function registerPwaIconsTypes(ctx, runtimeDir) {
|
|
313
|
-
const { options, nuxt, resolver } = ctx;
|
|
314
|
-
const pwaAssets = options.pwaAssets && !options.pwaAssets.disabled;
|
|
315
|
-
let dts;
|
|
316
|
-
if (pwaAssets) {
|
|
317
|
-
try {
|
|
318
|
-
const { preparePWAIconTypes } = await import('../chunks/pwa-icons.mjs');
|
|
319
|
-
dts = await preparePWAIconTypes(ctx);
|
|
320
|
-
} catch {
|
|
321
|
-
dts = void 0;
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
nuxt.options.alias["#pwa"] = resolver.resolve(runtimeDir, "composables/index");
|
|
325
|
-
nuxt.options.build.transpile.push("#pwa");
|
|
326
|
-
addImports([
|
|
327
|
-
"usePWA",
|
|
328
|
-
"useTransparentPwaIcon",
|
|
329
|
-
"useMaskablePwaIcon",
|
|
330
|
-
"useFaviconPwaIcon",
|
|
331
|
-
"useApplePwaIcon",
|
|
332
|
-
"useAppleSplashScreenPwaIcon"
|
|
333
|
-
].map((key) => ({
|
|
334
|
-
name: key,
|
|
335
|
-
as: key,
|
|
336
|
-
from: resolver.resolve(runtimeDir, "composables/index")
|
|
337
|
-
})));
|
|
338
|
-
const templates = [];
|
|
339
|
-
const isNuxt4 = ctx.nuxt4;
|
|
340
|
-
const dtsContent = dts?.dts;
|
|
341
|
-
if (dtsContent) {
|
|
342
|
-
templates.push(addTypeTemplate({
|
|
343
|
-
write: true,
|
|
344
|
-
filename: "pwa-icons/pwa-icons.d.ts",
|
|
345
|
-
getContents: () => dtsContent
|
|
346
|
-
}).dst);
|
|
347
|
-
} else {
|
|
348
|
-
templates.push(addTypeTemplate({
|
|
349
|
-
write: true,
|
|
350
|
-
filename: "pwa-icons/pwa-icons.d.ts",
|
|
351
|
-
getContents: () => pwaIcons()
|
|
352
|
-
}).dst);
|
|
353
|
-
}
|
|
354
|
-
templates.push(addPwaTypeTemplate("PwaTransparentImage", isNuxt4, dts?.transparent));
|
|
355
|
-
templates.push(addPwaTypeTemplate("PwaMaskableImage", isNuxt4, dts?.maskable));
|
|
356
|
-
templates.push(addPwaTypeTemplate("PwaFaviconImage", isNuxt4, dts?.favicon));
|
|
357
|
-
templates.push(addPwaTypeTemplate("PwaAppleImage", isNuxt4, dts?.apple));
|
|
358
|
-
templates.push(addPwaTypeTemplate("PwaAppleSplashScreenImage", isNuxt4, dts?.appleSplashScreen));
|
|
359
|
-
if (ctx.nuxt4) {
|
|
360
|
-
ctx.nuxt.hook("prepare:types", (context) => {
|
|
361
|
-
const nodeReferences = context.nodeReferences;
|
|
362
|
-
for (const path of templates) {
|
|
363
|
-
nodeReferences.push({ path });
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
return !!dts;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
async function regeneratePWA(_dir, pwaAssets, api) {
|
|
371
|
-
if (pwaAssets) {
|
|
372
|
-
const pwaAssetsGenerator = await api?.pwaAssetsGenerator();
|
|
373
|
-
if (pwaAssetsGenerator)
|
|
374
|
-
await pwaAssetsGenerator.generate();
|
|
375
|
-
}
|
|
376
|
-
if (!api || api.disabled)
|
|
377
|
-
return;
|
|
378
|
-
await api.generateSW();
|
|
379
|
-
}
|
|
380
|
-
async function writeWebManifest(dir, path, api, pwaAssets) {
|
|
381
|
-
if (pwaAssets) {
|
|
382
|
-
const pwaAssetsGenerator = await api.pwaAssetsGenerator();
|
|
383
|
-
if (pwaAssetsGenerator)
|
|
384
|
-
pwaAssetsGenerator.injectManifestIcons();
|
|
385
|
-
}
|
|
386
|
-
const manifest = api.generateBundle({})?.[path];
|
|
387
|
-
if (manifest && "source" in manifest)
|
|
388
|
-
await writeFile(resolve(dir, path), manifest.source, "utf-8");
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
async function doSetup(options, nuxt) {
|
|
392
|
-
const resolver = createResolver(import.meta.url);
|
|
393
|
-
const nuxtVersion = getNuxtVersion(nuxt).split(".").map((v) => Number.parseInt(v));
|
|
394
|
-
const nuxt3_8 = nuxtVersion.length > 1 && (nuxtVersion[0] > 3 || nuxtVersion[0] === 3 && nuxtVersion[1] >= 8);
|
|
395
|
-
const nuxt4 = nuxtVersion.length > 1 && nuxtVersion[0] >= 4;
|
|
396
|
-
const future = nuxt.options.future;
|
|
397
|
-
const ctx = {
|
|
398
|
-
nuxt,
|
|
399
|
-
nuxt3_8,
|
|
400
|
-
nuxt4,
|
|
401
|
-
// included at v3.12.0, then removed and included back again for v5 compatibility: we only need the layout to configure correctly the pwa assets image
|
|
402
|
-
// https://github.com/nuxt/nuxt/releases/tag/v3.12.0
|
|
403
|
-
nuxt4Compat: nuxt4 ? true : "compatibilityVersion" in future && typeof future.compatibilityVersion === "number" && future.compatibilityVersion >= 4,
|
|
404
|
-
resolver: createResolver(import.meta.url),
|
|
405
|
-
options,
|
|
406
|
-
publicDirFolder: resolveAlias("public")
|
|
407
|
-
};
|
|
408
|
-
let vitePwaClientPlugin;
|
|
409
|
-
const resolveVitePluginPWAAPI = () => {
|
|
410
|
-
return vitePwaClientPlugin?.api;
|
|
411
|
-
};
|
|
412
|
-
const client = options.client ?? {
|
|
413
|
-
registerPlugin: true,
|
|
414
|
-
installPrompt: false,
|
|
415
|
-
periodicSyncForUpdates: 0
|
|
416
|
-
};
|
|
417
|
-
const runtimeDir = resolver.resolve("../runtime");
|
|
418
|
-
nuxt.options.build.transpile.push(runtimeDir);
|
|
419
|
-
if (client.registerPlugin) {
|
|
420
|
-
addPlugin({
|
|
421
|
-
src: resolver.resolve(runtimeDir, "plugins/pwa.client"),
|
|
422
|
-
mode: "client"
|
|
423
|
-
});
|
|
424
|
-
}
|
|
425
|
-
const pwaAssetsEnabled = !!options.pwaAssets && options.pwaAssets.disabled !== true;
|
|
426
|
-
addPWAIconsPluginTemplate(pwaAssetsEnabled);
|
|
427
|
-
if (ctx.nuxt4) {
|
|
428
|
-
await Promise.all([
|
|
429
|
-
addComponent({
|
|
430
|
-
name: "VitePwaManifest",
|
|
431
|
-
filePath: resolver.resolve(runtimeDir, "components/VitePwaManifest")
|
|
432
|
-
}),
|
|
433
|
-
addComponent({
|
|
434
|
-
name: "NuxtPwaManifest",
|
|
435
|
-
filePath: resolver.resolve(runtimeDir, "components/VitePwaManifest")
|
|
436
|
-
}),
|
|
437
|
-
addComponent({
|
|
438
|
-
name: "NuxtPwaAssets",
|
|
439
|
-
filePath: resolver.resolve(runtimeDir, "components/NuxtPwaAssets")
|
|
440
|
-
}),
|
|
441
|
-
addComponent({
|
|
442
|
-
name: "PwaAppleImage",
|
|
443
|
-
filePath: resolver.resolve(runtimeDir, "components/nuxt4/PwaAppleImage")
|
|
444
|
-
}),
|
|
445
|
-
addComponent({
|
|
446
|
-
name: "PwaAppleSplashScreenImage",
|
|
447
|
-
filePath: resolver.resolve(runtimeDir, "components/nuxt4/PwaAppleSplashScreenImage")
|
|
448
|
-
}),
|
|
449
|
-
addComponent({
|
|
450
|
-
name: "PwaFaviconImage",
|
|
451
|
-
filePath: resolver.resolve(runtimeDir, "components/nuxt4/PwaFaviconImage")
|
|
452
|
-
}),
|
|
453
|
-
addComponent({
|
|
454
|
-
name: "PwaMaskableImage",
|
|
455
|
-
filePath: resolver.resolve(runtimeDir, "components/nuxt4/PwaMaskableImage")
|
|
456
|
-
}),
|
|
457
|
-
addComponent({
|
|
458
|
-
name: "PwaTransparentImage",
|
|
459
|
-
filePath: resolver.resolve(runtimeDir, "components/nuxt4/PwaTransparentImage")
|
|
460
|
-
})
|
|
461
|
-
]);
|
|
462
|
-
} else {
|
|
463
|
-
await Promise.all([
|
|
464
|
-
addComponent({
|
|
465
|
-
name: "VitePwaManifest",
|
|
466
|
-
filePath: resolver.resolve(runtimeDir, "components/VitePwaManifest")
|
|
467
|
-
}),
|
|
468
|
-
addComponent({
|
|
469
|
-
name: "NuxtPwaManifest",
|
|
470
|
-
filePath: resolver.resolve(runtimeDir, "components/VitePwaManifest")
|
|
471
|
-
}),
|
|
472
|
-
addComponent({
|
|
473
|
-
name: "NuxtPwaAssets",
|
|
474
|
-
filePath: resolver.resolve(runtimeDir, "components/NuxtPwaAssets")
|
|
475
|
-
}),
|
|
476
|
-
addComponent({
|
|
477
|
-
name: "PwaAppleImage",
|
|
478
|
-
filePath: resolver.resolve(runtimeDir, "components/PwaAppleImage.vue")
|
|
479
|
-
}),
|
|
480
|
-
addComponent({
|
|
481
|
-
name: "PwaAppleSplashScreenImage",
|
|
482
|
-
filePath: resolver.resolve(runtimeDir, "components/PwaAppleSplashScreenImage.vue")
|
|
483
|
-
}),
|
|
484
|
-
addComponent({
|
|
485
|
-
name: "PwaFaviconImage",
|
|
486
|
-
filePath: resolver.resolve(runtimeDir, "components/PwaFaviconImage.vue")
|
|
487
|
-
}),
|
|
488
|
-
addComponent({
|
|
489
|
-
name: "PwaMaskableImage",
|
|
490
|
-
filePath: resolver.resolve(runtimeDir, "components/PwaMaskableImage.vue")
|
|
491
|
-
}),
|
|
492
|
-
addComponent({
|
|
493
|
-
name: "PwaTransparentImage",
|
|
494
|
-
filePath: resolver.resolve(runtimeDir, "components/PwaTransparentImage.vue")
|
|
495
|
-
})
|
|
496
|
-
]);
|
|
497
|
-
}
|
|
498
|
-
nuxt.hook("prepare:types", ({ references }) => {
|
|
499
|
-
references.push({ path: resolver.resolve(runtimeDir, "plugins/types") });
|
|
500
|
-
references.push({ types: "@vite-pwa/nuxt/configuration" });
|
|
501
|
-
references.push({ types: "vite-plugin-pwa/vue" });
|
|
502
|
-
references.push({ types: "vite-plugin-pwa/info" });
|
|
503
|
-
references.push({ types: "vite-plugin-pwa/pwa-assets" });
|
|
504
|
-
});
|
|
505
|
-
const pwaAssets = await registerPwaIconsTypes(ctx, runtimeDir);
|
|
506
|
-
const manifestDir = join(nuxt.options.buildDir, "manifests");
|
|
507
|
-
nuxt.options.nitro.publicAssets = nuxt.options.nitro.publicAssets || [];
|
|
508
|
-
nuxt.options.nitro.publicAssets.push({
|
|
509
|
-
dir: manifestDir,
|
|
510
|
-
maxAge: 0
|
|
511
|
-
});
|
|
512
|
-
nuxt.hook("nitro:init", (nitro) => {
|
|
513
|
-
configurePWAOptions(ctx, nitro.options);
|
|
514
|
-
});
|
|
515
|
-
nuxt.hook("vite:extend", ({ config }) => {
|
|
516
|
-
const plugin = config.plugins?.find((p) => p && typeof p === "object" && "name" in p && p.name === "vite-plugin-pwa");
|
|
517
|
-
if (plugin)
|
|
518
|
-
throw new Error("Remove vite-plugin-pwa plugin from Vite Plugins entry in Nuxt config file!");
|
|
519
|
-
});
|
|
520
|
-
nuxt.hook("vite:extendConfig", async (viteInlineConfig, { isClient }) => {
|
|
521
|
-
viteInlineConfig.plugins = viteInlineConfig.plugins || [];
|
|
522
|
-
const plugin = viteInlineConfig.plugins.find((p) => p && typeof p === "object" && "name" in p && p.name === "vite-plugin-pwa");
|
|
523
|
-
if (plugin)
|
|
524
|
-
throw new Error("Remove vite-plugin-pwa plugin from Vite Plugins entry in Nuxt config file!");
|
|
525
|
-
if (options.manifest && isClient) {
|
|
526
|
-
viteInlineConfig.plugins.push({
|
|
527
|
-
name: "vite-pwa-nuxt:webmanifest:build",
|
|
528
|
-
apply: "build",
|
|
529
|
-
async writeBundle(_options, bundle) {
|
|
530
|
-
if (options.disable || !bundle)
|
|
531
|
-
return;
|
|
532
|
-
const api = resolveVitePluginPWAAPI();
|
|
533
|
-
if (api) {
|
|
534
|
-
await mkdir(manifestDir, { recursive: true });
|
|
535
|
-
await writeWebManifest(manifestDir, options.manifestFilename || "manifest.webmanifest", api, pwaAssets);
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
});
|
|
539
|
-
}
|
|
540
|
-
if (isClient) {
|
|
541
|
-
viteInlineConfig.plugins = viteInlineConfig.plugins || [];
|
|
542
|
-
const configuration = "virtual:nuxt-pwa-configuration";
|
|
543
|
-
const resolvedConfiguration = `\0${configuration}`;
|
|
544
|
-
viteInlineConfig.plugins.push({
|
|
545
|
-
name: "vite-pwa-nuxt:configuration",
|
|
546
|
-
enforce: "pre",
|
|
547
|
-
resolveId(id) {
|
|
548
|
-
if (id === configuration)
|
|
549
|
-
return resolvedConfiguration;
|
|
550
|
-
},
|
|
551
|
-
load(id) {
|
|
552
|
-
if (id === resolvedConfiguration) {
|
|
553
|
-
const display = typeof options.manifest !== "boolean" ? options.manifest?.display ?? "standalone" : "standalone";
|
|
554
|
-
const installPrompt = typeof client.installPrompt === "undefined" || client.installPrompt === false ? void 0 : client.installPrompt === true || client.installPrompt.trim() === "" ? "vite-pwa:hide-install" : client.installPrompt.trim();
|
|
555
|
-
return `export const enabled = ${client.registerPlugin}
|
|
556
|
-
export const display = '${display}'
|
|
557
|
-
export const installPrompt = ${JSON.stringify(installPrompt)}
|
|
558
|
-
export const periodicSyncForUpdates = ${typeof client.periodicSyncForUpdates === "number" ? client.periodicSyncForUpdates : 0}
|
|
559
|
-
`;
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
});
|
|
563
|
-
}
|
|
564
|
-
const plugins = [...VitePWA(options).filter((p) => p.name !== "vite-plugin-pwa:build")];
|
|
565
|
-
viteInlineConfig.plugins.push(plugins);
|
|
566
|
-
if (isClient)
|
|
567
|
-
vitePwaClientPlugin = plugins.find((p) => p.name === "vite-plugin-pwa");
|
|
568
|
-
});
|
|
569
|
-
extendWebpackConfig(() => {
|
|
570
|
-
throw new Error("Webpack is not supported: @vite-pwa/nuxt module can only be used with Vite!");
|
|
571
|
-
});
|
|
572
|
-
if (nuxt.options.dev) {
|
|
573
|
-
const webManifest = `${nuxt.options.app.baseURL}${options.devOptions?.webManifestUrl ?? options.manifestFilename ?? "manifest.webmanifest"}`;
|
|
574
|
-
const devSw = `${nuxt.options.app.baseURL}dev-sw.js?dev-sw`;
|
|
575
|
-
const workbox = `${nuxt.options.app.baseURL}workbox-`;
|
|
576
|
-
const emptyHandle = (_req, _res, next) => {
|
|
577
|
-
next();
|
|
578
|
-
};
|
|
579
|
-
nuxt.hook("vite:serverCreated", (viteServer, { isServer }) => {
|
|
580
|
-
if (isServer)
|
|
581
|
-
return;
|
|
582
|
-
viteServer.middlewares.stack.push({ route: webManifest, handle: emptyHandle });
|
|
583
|
-
viteServer.middlewares.stack.push({ route: devSw, handle: emptyHandle });
|
|
584
|
-
if (options.pwaAssets) {
|
|
585
|
-
viteServer.middlewares.stack.push({
|
|
586
|
-
route: "",
|
|
587
|
-
// @ts-expect-error just ignore
|
|
588
|
-
handle: async (req, res, next) => {
|
|
589
|
-
const url = req.url;
|
|
590
|
-
if (!url)
|
|
591
|
-
return next();
|
|
592
|
-
if (!/\.(?:ico|png|svg|webp)$/.test(url))
|
|
593
|
-
return next();
|
|
594
|
-
const pwaAssetsGenerator = await resolveVitePluginPWAAPI()?.pwaAssetsGenerator();
|
|
595
|
-
if (!pwaAssetsGenerator)
|
|
596
|
-
return next();
|
|
597
|
-
const icon = await pwaAssetsGenerator.findIconAsset(url);
|
|
598
|
-
if (!icon)
|
|
599
|
-
return next();
|
|
600
|
-
if (icon.age > 0) {
|
|
601
|
-
const ifModifiedSince = req.headers["if-modified-since"] ?? req.headers["If-Modified-Since"];
|
|
602
|
-
const useIfModifiedSince = ifModifiedSince ? Array.isArray(ifModifiedSince) ? ifModifiedSince[0] : ifModifiedSince : void 0;
|
|
603
|
-
if (useIfModifiedSince && new Date(icon.lastModified).getTime() / 1e3 >= new Date(useIfModifiedSince).getTime() / 1e3) {
|
|
604
|
-
res.statusCode = 304;
|
|
605
|
-
res.end();
|
|
606
|
-
return;
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
const buffer = await icon.buffer;
|
|
610
|
-
res.setHeader("Age", icon.age / 1e3);
|
|
611
|
-
res.setHeader("Content-Type", icon.mimeType);
|
|
612
|
-
res.setHeader("Content-Length", buffer.length);
|
|
613
|
-
res.setHeader("Last-Modified", new Date(icon.lastModified).toUTCString());
|
|
614
|
-
res.statusCode = 200;
|
|
615
|
-
res.end(buffer);
|
|
616
|
-
}
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
});
|
|
620
|
-
if (!options.strategies || options.strategies === "generateSW") {
|
|
621
|
-
nuxt.hook("vite:serverCreated", (viteServer, { isServer }) => {
|
|
622
|
-
if (isServer)
|
|
623
|
-
return;
|
|
624
|
-
viteServer.middlewares.stack.push({ route: workbox, handle: emptyHandle });
|
|
625
|
-
});
|
|
626
|
-
if (options.devOptions?.suppressWarnings) {
|
|
627
|
-
const suppressWarnings = `${nuxt.options.app.baseURL}suppress-warnings.js`;
|
|
628
|
-
nuxt.hook("vite:serverCreated", (viteServer, { isServer }) => {
|
|
629
|
-
if (isServer)
|
|
630
|
-
return;
|
|
631
|
-
viteServer.middlewares.stack.push({ route: suppressWarnings, handle: emptyHandle });
|
|
632
|
-
});
|
|
633
|
-
}
|
|
634
|
-
const { sourcemap = nuxt.options.sourcemap.client === true } = options.workbox ?? {};
|
|
635
|
-
if (sourcemap) {
|
|
636
|
-
const swMap = `${nuxt.options.app.baseURL}${options.filename ?? "sw.js"}.map`;
|
|
637
|
-
const resolvedSwMapFile = join(nuxt.options.buildDir, "dev-sw-dist", swMap);
|
|
638
|
-
const worboxMap = `${nuxt.options.app.baseURL}workbox-`;
|
|
639
|
-
addDevServerHandler({
|
|
640
|
-
route: "",
|
|
641
|
-
handler: await import('h3').then(({ defineLazyEventHandler }) => defineLazyEventHandler(async () => {
|
|
642
|
-
const { dev } = await import('../chunks/dev.mjs');
|
|
643
|
-
return dev(
|
|
644
|
-
swMap,
|
|
645
|
-
resolvedSwMapFile,
|
|
646
|
-
worboxMap,
|
|
647
|
-
nuxt.options.buildDir,
|
|
648
|
-
nuxt.options.app.baseURL
|
|
649
|
-
);
|
|
650
|
-
}))
|
|
651
|
-
});
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
} else {
|
|
655
|
-
if (!options.disable && options.registerWebManifestInRouteRules) {
|
|
656
|
-
nuxt.hook("nitro:config", async (nitroConfig) => {
|
|
657
|
-
nitroConfig.routeRules = nitroConfig.routeRules || {};
|
|
658
|
-
let swName = options.filename || "sw.js";
|
|
659
|
-
if (options.strategies === "injectManifest" && swName.endsWith(".ts"))
|
|
660
|
-
swName = swName.replace(/\.ts$/, ".js");
|
|
661
|
-
nitroConfig.routeRules[`${nuxt.options.app.baseURL}${swName}`] = {
|
|
662
|
-
headers: {
|
|
663
|
-
"Cache-Control": "public, max-age=0, must-revalidate"
|
|
664
|
-
}
|
|
665
|
-
};
|
|
666
|
-
if (options.manifest) {
|
|
667
|
-
nitroConfig.routeRules[`${nuxt.options.app.baseURL}${options.manifestFilename ?? "manifest.webmanifest"}`] = {
|
|
668
|
-
headers: {
|
|
669
|
-
"Content-Type": "application/manifest+json",
|
|
670
|
-
"Cache-Control": "public, max-age=0, must-revalidate"
|
|
671
|
-
}
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
if (nuxt3_8) {
|
|
677
|
-
nuxt.hook("nitro:build:public-assets", async () => {
|
|
678
|
-
await regeneratePWA(
|
|
679
|
-
options.outDir,
|
|
680
|
-
pwaAssets,
|
|
681
|
-
resolveVitePluginPWAAPI()
|
|
682
|
-
);
|
|
683
|
-
});
|
|
684
|
-
} else {
|
|
685
|
-
nuxt.hook("nitro:init", (nitro) => {
|
|
686
|
-
nitro.hooks.hook("rollup:before", async () => {
|
|
687
|
-
await regeneratePWA(
|
|
688
|
-
options.outDir,
|
|
689
|
-
pwaAssets,
|
|
690
|
-
resolveVitePluginPWAAPI()
|
|
691
|
-
);
|
|
692
|
-
});
|
|
693
|
-
});
|
|
694
|
-
if (nuxt.options.nitro.static || nuxt.options._generate) {
|
|
695
|
-
nuxt.hook("close", async () => {
|
|
696
|
-
await regeneratePWA(
|
|
697
|
-
options.outDir,
|
|
698
|
-
pwaAssets,
|
|
699
|
-
resolveVitePluginPWAAPI()
|
|
700
|
-
);
|
|
701
|
-
});
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
const module = defineNuxtModule({
|
|
708
|
-
meta: {
|
|
709
|
-
name: "@vite-pwa/nuxt",
|
|
710
|
-
configKey: "pwa",
|
|
711
|
-
compatibility: {
|
|
712
|
-
nuxt: ">=3.6.5"
|
|
713
|
-
},
|
|
714
|
-
version
|
|
715
|
-
},
|
|
716
|
-
defaults: (nuxt) => ({
|
|
717
|
-
base: nuxt.options.app.baseURL,
|
|
718
|
-
scope: nuxt.options.app.baseURL,
|
|
719
|
-
injectRegister: false,
|
|
720
|
-
includeManifestIcons: false,
|
|
721
|
-
registerPlugin: true,
|
|
722
|
-
writePlugin: false,
|
|
723
|
-
client: {
|
|
724
|
-
registerPlugin: true,
|
|
725
|
-
installPrompt: false,
|
|
726
|
-
periodicSyncForUpdates: 0
|
|
727
|
-
}
|
|
728
|
-
}),
|
|
729
|
-
async setup(options, nuxt) {
|
|
730
|
-
await doSetup(options, nuxt);
|
|
731
|
-
}
|
|
732
|
-
});
|
|
733
|
-
|
|
734
|
-
export { generatePwaImageType as g, module as m, pwaIcons as p };
|