0
# PWA Information and Assets
1
2
Virtual modules providing access to PWA information, generated assets, and metadata for integrations and custom implementations.
3
4
## Capabilities
5
6
### PWA Information Module
7
8
Access to PWA configuration and runtime information.
9
10
```typescript { .api }
11
// Virtual module: virtual:pwa-info
12
/**
13
* PWA information object containing web manifest and service worker data
14
* Available only when PWA is enabled and not in SSR builds
15
*/
16
const pwaInfo: PwaInfo | undefined;
17
18
interface PwaInfo {
19
/** Whether PWA is running in development environment */
20
pwaInDevEnvironment: boolean;
21
/** Web manifest information - always present when pwaInfo is available */
22
webManifest: {
23
/** URL to the web manifest file */
24
href: string;
25
/** Whether to use credentials for manifest requests */
26
useCredentials: boolean;
27
/** Complete link tag for the web manifest */
28
linkTag: string;
29
};
30
/** Service worker registration information - conditionally present */
31
registerSW?: {
32
/** @deprecated Use mode instead */
33
inline: boolean;
34
/** Registration mode - inline script or external script */
35
mode: 'inline' | 'script' | 'script-defer';
36
/** Path for inline service worker registration script */
37
inlinePath: string;
38
/** Path for external service worker registration script */
39
registerPath: string;
40
/** Service worker scope */
41
scope: string;
42
/** Service worker type */
43
type: 'classic' | 'module';
44
/** Complete script tag for service worker registration */
45
scriptTag?: string;
46
};
47
}
48
```
49
50
**Usage Example:**
51
52
```typescript
53
import { pwaInfo } from "virtual:pwa-info";
54
55
// Use in framework integrations or custom implementations
56
if (pwaInfo) {
57
console.log("PWA is enabled");
58
console.log("Manifest URL:", pwaInfo.webManifest.href);
59
60
// Add manifest link to head
61
document.head.insertAdjacentHTML("beforeend", pwaInfo.webManifest.linkTag);
62
63
// Handle service worker registration
64
if (pwaInfo.registerSW && pwaInfo.registerSW.scriptTag) {
65
document.head.insertAdjacentHTML("beforeend", pwaInfo.registerSW.scriptTag);
66
}
67
} else {
68
console.log("PWA is disabled or in SSR mode");
69
}
70
71
// Framework integration example
72
function usePWAInfo() {
73
return {
74
isPWAEnabled: !!pwaInfo,
75
isDevEnvironment: pwaInfo?.pwaInDevEnvironment ?? false,
76
manifestUrl: pwaInfo?.webManifest.href,
77
hasServiceWorker: !!pwaInfo?.registerSW,
78
};
79
}
80
```
81
82
### PWA Assets Head Module
83
84
Access to generated PWA assets for HTML head injection.
85
86
```typescript { .api }
87
// Virtual module: virtual:pwa-assets/head
88
/**
89
* PWA assets head configuration with links and theme color
90
* Available when PWA assets generation is enabled
91
*/
92
const pwaAssetsHead: PWAAssetsHead;
93
94
interface PWAAssetsHead {
95
/** Array of head link elements for PWA assets */
96
links: PWAAssetHeadLink[];
97
/** Theme color meta tag configuration */
98
themeColor?: ColorSchemeMeta;
99
}
100
101
interface PWAAssetHeadLink {
102
/** Optional link ID for targeting */
103
id?: string;
104
/** Link relationship type */
105
rel: 'apple-touch-startup-image' | 'apple-touch-icon' | 'icon';
106
/** Asset URL */
107
href: string;
108
/** Media query for responsive assets */
109
media?: string;
110
/** Icon sizes specification */
111
sizes?: string;
112
/** MIME type of the asset */
113
type?: string;
114
}
115
116
interface ColorSchemeMeta {
117
/** Meta tag name attribute */
118
name: string;
119
/** Meta tag content attribute */
120
content: string;
121
}
122
```
123
124
**Usage Example:**
125
126
```typescript
127
import { pwaAssetsHead } from "virtual:pwa-assets/head";
128
129
// Inject PWA assets into HTML head
130
function injectPWAAssets() {
131
const head = document.head;
132
133
// Inject icon and splash screen links
134
pwaAssetsHead.links.forEach((link) => {
135
const linkElement = document.createElement("link");
136
linkElement.rel = link.rel;
137
linkElement.href = link.href;
138
139
if (link.id) linkElement.id = link.id;
140
if (link.sizes) linkElement.setAttribute("sizes", link.sizes);
141
if (link.type) linkElement.type = link.type;
142
if (link.media) linkElement.media = link.media;
143
144
head.appendChild(linkElement);
145
});
146
147
// Inject theme color meta tag
148
if (pwaAssetsHead.themeColor) {
149
const metaElement = document.createElement("meta");
150
metaElement.name = pwaAssetsHead.themeColor.name;
151
metaElement.content = pwaAssetsHead.themeColor.content;
152
head.appendChild(metaElement);
153
}
154
}
155
156
// Framework integration example (React)
157
function PWAHeadAssets() {
158
return (
159
<>
160
{pwaAssetsHead.links.map((link, index) => (
161
<link
162
key={link.id || index}
163
rel={link.rel}
164
href={link.href}
165
{...(link.sizes && { sizes: link.sizes })}
166
{...(link.type && { type: link.type })}
167
{...(link.media && { media: link.media })}
168
/>
169
))}
170
{pwaAssetsHead.themeColor && (
171
<meta
172
name={pwaAssetsHead.themeColor.name}
173
content={pwaAssetsHead.themeColor.content}
174
/>
175
)}
176
</>
177
);
178
}
179
```
180
181
### PWA Assets Icons Module
182
183
Access to generated PWA icon assets organized by type and purpose.
184
185
```typescript { .api }
186
// Virtual module: virtual:pwa-assets/icons
187
/**
188
* PWA assets icons collection organized by type
189
* Available when PWA assets generation is enabled
190
*/
191
const pwaAssetsIcons: PWAAssetsIcons;
192
193
interface PWAAssetsIcons {
194
/** Favicon icons for browser tabs */
195
favicon: Record<string, PWAAssetIcon<FaviconLink>>;
196
/** Transparent background icons */
197
transparent: Record<string, PWAAssetIcon<HtmlLink>>;
198
/** Maskable icons for adaptive icon support */
199
maskable: Record<string, PWAAssetIcon<HtmlLink>>;
200
/** Apple-specific touch icons */
201
apple: Record<string, PWAAssetIcon<HtmlLink>>;
202
/** Apple splash screen images */
203
appleSplashScreen: Record<string, PWAAssetIcon<AppleSplashScreenLink>>;
204
}
205
206
type PWAAssetIcon<T extends HtmlLink> = Omit<IconAsset<T>, 'buffer'>;
207
208
interface IconAsset<T extends HtmlLink> {
209
/** Asset name/identifier */
210
name: string;
211
/** Asset file path */
212
src: string;
213
/** Icon dimensions */
214
size: { width: number; height: number };
215
/** HTML link configuration */
216
htmlLink: T;
217
}
218
219
interface HtmlLink {
220
rel: string;
221
href: string;
222
sizes?: string;
223
type?: string;
224
}
225
226
interface FaviconLink extends HtmlLink {
227
rel: 'icon';
228
}
229
230
interface AppleSplashScreenLink extends HtmlLink {
231
rel: 'apple-touch-startup-image';
232
media: string;
233
}
234
```
235
236
**Usage Example:**
237
238
```typescript
239
import { pwaAssetsIcons } from "virtual:pwa-assets/icons";
240
241
// Access different icon types
242
function logIconAssets() {
243
console.log("Favicon icons:", Object.keys(pwaAssetsIcons.favicon));
244
console.log("Transparent icons:", Object.keys(pwaAssetsIcons.transparent));
245
console.log("Maskable icons:", Object.keys(pwaAssetsIcons.maskable));
246
console.log("Apple icons:", Object.keys(pwaAssetsIcons.apple));
247
console.log("Apple splash screens:", Object.keys(pwaAssetsIcons.appleSplashScreen));
248
}
249
250
// Create manifest icons from generated assets
251
function createManifestIcons() {
252
const icons = [];
253
254
// Add transparent icons to manifest
255
Object.values(pwaAssetsIcons.transparent).forEach((icon) => {
256
icons.push({
257
src: icon.src,
258
sizes: `${icon.size.width}x${icon.size.height}`,
259
type: icon.htmlLink.type || "image/png",
260
purpose: "any",
261
});
262
});
263
264
// Add maskable icons to manifest
265
Object.values(pwaAssetsIcons.maskable).forEach((icon) => {
266
icons.push({
267
src: icon.src,
268
sizes: `${icon.size.width}x${icon.size.height}`,
269
type: icon.htmlLink.type || "image/png",
270
purpose: "maskable",
271
});
272
});
273
274
return icons;
275
}
276
277
// Framework integration example (Vue)
278
function usePWAIcons() {
279
return {
280
favicon: computed(() => pwaAssetsIcons.favicon),
281
transparent: computed(() => pwaAssetsIcons.transparent),
282
maskable: computed(() => pwaAssetsIcons.maskable),
283
apple: computed(() => pwaAssetsIcons.apple),
284
appleSplashScreen: computed(() => pwaAssetsIcons.appleSplashScreen),
285
286
// Helper to get icon by size
287
getIconBySize: (type: keyof PWAAssetsIcons, size: string) => {
288
const icons = pwaAssetsIcons[type];
289
return Object.values(icons).find(
290
(icon) => `${icon.size.width}x${icon.size.height}` === size
291
);
292
},
293
294
// Helper to create HTML links
295
createHtmlLinks: (type: keyof PWAAssetsIcons) => {
296
return Object.values(pwaAssetsIcons[type]).map((icon) => icon.htmlLink);
297
},
298
};
299
}
300
```
301
302
## Integration Patterns
303
304
### Server-Side Rendering (SSR)
305
306
Handle PWA info and assets in SSR environments:
307
308
```typescript
309
// Check availability before use
310
function getSSRPWAInfo() {
311
try {
312
const info = pwaInfo;
313
return info || null;
314
} catch {
315
// Module not available in SSR
316
return null;
317
}
318
}
319
320
// Conditional asset injection
321
function injectPWAAssetsSSR() {
322
try {
323
const assets = pwaAssetsHead;
324
return assets.links.map(link =>
325
`<link rel="${link.rel}" href="${link.href}"${
326
link.sizes ? ` sizes="${link.sizes}"` : ''
327
}${link.type ? ` type="${link.type}"` : ''}${
328
link.media ? ` media="${link.media}"` : ''
329
}>`
330
).join('\n');
331
} catch {
332
return '';
333
}
334
}
335
```
336
337
### Meta Framework Integration
338
339
Integration patterns for popular meta-frameworks:
340
341
```typescript
342
// Next.js Head component integration
343
import Head from "next/head";
344
import { pwaAssetsHead } from "virtual:pwa-assets/head";
345
346
function PWAHead() {
347
return (
348
<Head>
349
{pwaAssetsHead.links.map((link, index) => (
350
<link
351
key={index}
352
rel={link.rel}
353
href={link.href}
354
sizes={link.sizes}
355
type={link.type}
356
media={link.media}
357
/>
358
))}
359
{pwaAssetsHead.themeColor && (
360
<meta
361
name={pwaAssetsHead.themeColor.name}
362
content={pwaAssetsHead.themeColor.content}
363
/>
364
)}
365
</Head>
366
);
367
}
368
369
// Nuxt.js useHead integration
370
import { useHead } from "@vueuse/head";
371
import { pwaAssetsHead } from "virtual:pwa-assets/head";
372
373
function usePWAHead() {
374
useHead({
375
link: pwaAssetsHead.links,
376
meta: pwaAssetsHead.themeColor ? [pwaAssetsHead.themeColor] : [],
377
});
378
}
379
```
380
381
### Dynamic Asset Loading
382
383
Load PWA assets dynamically based on conditions:
384
385
```typescript
386
import { pwaAssetsIcons } from "virtual:pwa-assets/icons";
387
388
async function loadOptimalIcon(preferredSize = "192x192") {
389
// Try to find icon with preferred size
390
const transparent = Object.values(pwaAssetsIcons.transparent);
391
let icon = transparent.find(
392
(icon) => `${icon.size.width}x${icon.size.height}` === preferredSize
393
);
394
395
// Fall back to first available icon
396
if (!icon && transparent.length > 0) {
397
icon = transparent[0];
398
}
399
400
if (icon) {
401
// Preload the icon
402
const link = document.createElement("link");
403
link.rel = "preload";
404
link.as = "image";
405
link.href = icon.src;
406
document.head.appendChild(link);
407
408
return icon;
409
}
410
411
return null;
412
}
413
```