Skip to content

Commit

Permalink
fix: add SPA support
Browse files Browse the repository at this point in the history
  • Loading branch information
userquin committed Dec 30, 2024
1 parent 18702f4 commit 1f89d48
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 2 deletions.
52 changes: 50 additions & 2 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { resolve } from 'node:path'
import crypto from 'node:crypto'
import fs from 'node:fs'
import type { ResolvedConfig } from 'vite'
import type { VitePWAOptions } from 'vite-plugin-pwa'
import type { ManifestTransform } from 'workbox-build'
import type { ManifestEntry, ManifestTransform } from 'workbox-build'
import type { KitOptions } from './types'

export function configureSvelteKitOptions(
Expand Down Expand Up @@ -76,6 +78,7 @@ export function configureSvelteKitOptions(
if (!config.manifestTransforms) {
config.manifestTransforms = [createManifestTransform(
base,
config.globDirectory,
options.strategies === 'injectManifest'
? undefined
: (options.manifestFilename ?? 'manifest.webmanifest'),
Expand All @@ -92,7 +95,12 @@ export function configureSvelteKitOptions(
}
}

function createManifestTransform(base: string, webManifestName?: string, options?: KitOptions): ManifestTransform {
function createManifestTransform(
base: string,
outDir: string,
webManifestName?: string,
options?: KitOptions,
): ManifestTransform {
return async (entries) => {
const defaultAdapterFallback = 'prerendered/fallback.html'
const suffix = options?.trailingSlash === 'always' ? '/' : ''
Expand Down Expand Up @@ -149,6 +157,25 @@ function createManifestTransform(base: string, webManifestName?: string, options
return e
})

if (options?.spa && options?.adapterFallback) {
const name = typeof options.spa === 'object' && options.spa.fallbackMapping
? options.spa.fallbackMapping
: options.adapterFallback
if (typeof options.spa === 'object' && typeof options.spa.fallbackRevision === 'function') {
manifest.push({
url: name,
revision: await options.spa.fallbackRevision(),
size: 0,
})
}
else {
manifest.push(await buildManifestEntry(
name,
resolve(outDir, 'client/_app/version.json'),
))
}
}

if (!webManifestName)
return { manifest }

Expand Down Expand Up @@ -183,3 +210,24 @@ function buildGlobIgnores(globIgnores?: string[]) {

return ['server/**']
}

function buildManifestEntry(url: string, path: string): Promise<ManifestEntry & { size: number }> {
return new Promise((resolve, reject) => {
const cHash = crypto.createHash('MD5')
const stream = fs.createReadStream(path)
stream.on('error', (err) => {
reject(err)
})
stream.on('data', (chunk) => {
// @ts-expect-error TS2345: Argument of type string | Buffer is not assignable to parameter of type BinaryLike
cHash.update(chunk)
})
stream.on('end', () => {
return resolve({
url,
size: 0,
revision: `${cHash.digest('hex')}`,
})
})
})
}
26 changes: 26 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,32 @@ export interface KitOptions {
* @default false
*/
includeVersionFile?: boolean

/**
* Enable SPA mode for the application.
*
* By default, the plugin will use `adapterFallback` to include the entry in the service worker
* precache manifest.
*
* If you are using a logical name for the fallback, you can use the object syntax with the
* `fallbackMapping`.
*
* For example, if you're using `fallback: 'app.html'` in your static adapter and your server
* is redirecting to `/app`, you can configure `fallbackMapping: '/app'`.
*
* Since the static adapter will run after the PWA plugin generates the service worker,
* the PWA plugin doesn't have access to the adapter fallback page to include the revision in the
* service worker precache manifest.
* To generate the revision for the fallback page, the PWA plugin will use the
* `.svelte-kit/output/client/_app/version.json` file.
* You can configure the `fallbackRevision` to generate a custom revision.
*
* @see https://svelte.dev/docs/kit/single-page-apps
*/
spa?: true | {
fallbackMapping?: string
fallbackRevision?: () => Promise<string>
}
}

export interface SvelteKitPWAOptions extends Partial<VitePWAOptions> {
Expand Down

0 comments on commit 1f89d48

Please sign in to comment.