1
+ import { lstat } from 'node:fs/promises'
2
+ import { createHash } from 'node:crypto'
3
+ import { createReadStream } from 'node:fs'
1
4
import type { Nuxt } from '@nuxt/schema'
2
5
import { resolve } from 'pathe'
3
6
import type { NitroConfig } from 'nitropack'
@@ -80,12 +83,16 @@ export function configurePWAOptions(
80
83
81
84
// allow override manifestTransforms
82
85
if ( ! nuxt . options . dev && ! config . manifestTransforms )
83
- config . manifestTransforms = [ createManifestTransform ( nuxt . options . app . baseURL ?? '/' , appManifestFolder ) ]
86
+ config . manifestTransforms = [ createManifestTransform ( nuxt . options . app . baseURL ?? '/' , options . outDir , appManifestFolder ) ]
84
87
}
85
88
86
- function createManifestTransform ( base : string , appManifestFolder ?: string ) : import ( 'workbox-build' ) . ManifestTransform {
89
+ function createManifestTransform (
90
+ base : string ,
91
+ publicFolder : string ,
92
+ appManifestFolder ?: string ,
93
+ ) : import ( 'workbox-build' ) . ManifestTransform {
87
94
return async ( entries ) => {
88
- entries . filter ( e => e && e . url . endsWith ( '.html' ) ) . forEach ( ( e ) => {
95
+ entries . filter ( e => e . url . endsWith ( '.html' ) ) . forEach ( ( e ) => {
89
96
const url = e . url . startsWith ( '/' ) ? e . url . slice ( 1 ) : e . url
90
97
if ( url === 'index.html' ) {
91
98
e . url = base
@@ -98,12 +105,39 @@ function createManifestTransform(base: string, appManifestFolder?: string): impo
98
105
} )
99
106
100
107
if ( appManifestFolder ) {
108
+ // this shouldn't be necessary, since we are using dontCacheBustURLsMatching
101
109
const regExp = / ( \/ ) ? [ 0 - 9 a - f ] { 8 } \b - [ 0 - 9 a - f ] { 4 } \b - [ 0 - 9 a - f ] { 4 } \b - [ 0 - 9 a - f ] { 4 } \b - [ 0 - 9 a - f ] { 12 } \. j s o n $ / i
102
110
// we need to remove the revision from the sw prechaing manifest, UUID is enough:
103
111
// we don't use dontCacheBustURLsMatching, single regex
104
- entries . filter ( e => e && e . url . startsWith ( appManifestFolder ) && regExp . test ( e . url ) ) . forEach ( ( e ) => {
112
+ entries . filter ( e => e . url . startsWith ( appManifestFolder ) && regExp . test ( e . url ) ) . forEach ( ( e ) => {
105
113
e . revision = null
106
114
} )
115
+ // add revision to latest.json file: we are excluding `_nuxt/` assets from dontCacheBustURLsMatching
116
+ const latest = `${ appManifestFolder } latest.json`
117
+ const latestJson = resolve ( publicFolder , latest )
118
+ const data = await lstat ( latestJson ) . catch ( ( ) => undefined )
119
+ if ( data ?. isFile ( ) ) {
120
+ const revision = await new Promise < string > ( ( resolve , reject ) => {
121
+ const cHash = createHash ( 'MD5' )
122
+ const stream = createReadStream ( latestJson )
123
+ stream . on ( 'error' , ( err ) => {
124
+ reject ( err )
125
+ } )
126
+ stream . on ( 'data' , chunk => cHash . update ( chunk ) )
127
+ stream . on ( 'end' , ( ) => {
128
+ resolve ( cHash . digest ( 'hex' ) )
129
+ } )
130
+ } )
131
+
132
+ const latestEntry = entries . find ( e => e . url === latest )
133
+ if ( latestEntry )
134
+ latestEntry . revision = revision
135
+ else
136
+ entries . push ( { url : latest , revision, size : data . size } )
137
+ }
138
+ else {
139
+ entries = entries . filter ( e => e . url !== latest )
140
+ }
107
141
}
108
142
109
143
return { manifest : entries , warnings : [ ] }
0 commit comments