vite-pwa / docs

Documentation: PWA integrations for Vite and the ecosystem
https://vite-pwa-org.netlify.app/
MIT License
196 stars 42 forks source link

Static assets having duplicate file revision when generating Service Worker precache #67

Closed lgaspari closed 1 year ago

lgaspari commented 1 year ago

Hello, I'm currently trying to configure the Service Worker precache so that I can cache all my files when installing the application but I noticed a strange behavior when trying different approaches using the Vite PWA docs.


Scenario 1: don't include assets nor use workbox glob patterns

If I configure the `VitePWA` plugin using the following configuration: ```ts VitePWA({ // Public resources // includeAssets: [], // Manifest configuration. // https://vite-pwa-org.netlify.app/guide/pwa-minimal-requirements.html manifest: { ..., icons: [ { src: 'pwa-64x64.png', sizes: '64x64', type: 'image/png', }, { src: 'pwa-192x192.png', sizes: '192x192', type: 'image/png', }, { src: 'pwa-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'any', }, { src: 'maskable-icon-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable', }, ], }, // Workbox configuration. // workbox: { // globPatterns: ['**/*.{js,css,html,ico,png,svg}'], // }, }), ``` Then, it would result in the following Service Worker precache after build. Please note that `public/` files are not being included as part of the precache array (e.g. `apple-touch-icon`, `favicon.ico`, `logo.svg`, `robots.txt` etc.), at least not like the [Static assets handling](https://vite-pwa-org.netlify.app/guide/static-assets.html#static-assets-handling) page statement. ```ts e.precacheAndRoute( [ { url: 'assets/index.0fb3162c.js', revision: null }, { url: 'assets/index.f0b36889.css', revision: null }, { url: 'assets/workbox-window.prod.es5.e0cc53cf.js', revision: null }, { url: 'index.html', revision: 'ecfa72ef5ede33cddcab4b29ddfff4ff' }, { url: 'pwa-64x64.png', revision: '160c4d06af493fa1cb62ae9f4258003b' }, { url: 'pwa-192x192.png', revision: '9397e91d5e3a42bfa03ce2d07f7e3171', }, { url: 'pwa-512x512.png', revision: '49e40aedc6b5cd06157f00d8c564e379', }, { url: 'maskable-icon-512x512.png', revision: 'a51a4f0cc05f269554afef971b7f658d', }, { url: 'manifest.webmanifest', revision: 'f9addcd4a864ed3a97c677e5274540c8', }, ], {} ), ```


Scenario 2: include assets but don't use workbox glob patterns

Moreover, if I configure the `VitePWA` plugin using the following configuration instead: ```ts VitePWA({ // Public resources includeAssets: [ 'apple-touch-icon-180x180', 'favicon.ico', 'logo.svg', 'robots.txt', ], // Manifest configuration. // https://vite-pwa-org.netlify.app/guide/pwa-minimal-requirements.html manifest: { ..., icons: [ { src: 'pwa-64x64.png', sizes: '64x64', type: 'image/png', }, { src: 'pwa-192x192.png', sizes: '192x192', type: 'image/png', }, { src: 'pwa-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'any', }, { src: 'maskable-icon-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable', }, ], }, // Workbox configuration. // workbox: { // globPatterns: ['**/*.{js,css,html,ico,png,svg}'], // }, }), ``` Then, it would result in the following Service Worker precache after build, which is more accurate to what I'm looking for. However, I'm still missing other valuable assets that were auto-generated by Vite using a hash in their name. ```ts e.precacheAndRoute( [ { url: 'assets/index.0fb3162c.js', revision: null }, { url: 'assets/index.f0b36889.css', revision: null }, { url: 'assets/workbox-window.prod.es5.e0cc53cf.js', revision: null }, { url: 'index.html', revision: 'ecfa72ef5ede33cddcab4b29ddfff4ff' }, { url: 'favicon.ico', revision: '547587c645ecf0155439c8e0edb6cb3d' }, { url: 'logo.svg', revision: '40dcf9f191738beb353d7a53edb8abd9' }, { url: 'robots.txt', revision: 'f77c87f977e0fcce05a6df46c885a129' }, { url: 'pwa-64x64.png', revision: '160c4d06af493fa1cb62ae9f4258003b' }, { url: 'pwa-192x192.png', revision: '9397e91d5e3a42bfa03ce2d07f7e3171', }, { url: 'pwa-512x512.png', revision: '49e40aedc6b5cd06157f00d8c564e379', }, { url: 'maskable-icon-512x512.png', revision: 'a51a4f0cc05f269554afef971b7f658d', }, { url: 'manifest.webmanifest', revision: 'f9addcd4a864ed3a97c677e5274540c8', }, ], {} ), ```


Scenario 3: don't include assets but use workbox glob patterns

Furthermore, if I configure the `VitePWA` plugin using the following configuration: ```ts VitePWA({ // Public resources // includeAssets: [], // Manifest configuration. // https://vite-pwa-org.netlify.app/guide/pwa-minimal-requirements.html manifest: { ..., icons: [ { src: 'pwa-64x64.png', sizes: '64x64', type: 'image/png', }, { src: 'pwa-192x192.png', sizes: '192x192', type: 'image/png', }, { src: 'pwa-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'any', }, { src: 'maskable-icon-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable', }, ], }, // Workbox configuration. workbox: { globPatterns: ['**/*.{js,css,html,ico,png,svg}'], }, }), ``` Then, it would result in the following Service Worker precache after build. Which is exactly what I'm looking for, but then you may notice that **there are duplicates in the output** from the manifest itself (e.g. `pwa-{size}` images). ```ts e.precacheAndRoute( [ { url: 'apple-touch-icon-180x180.png', revision: '9b7a985648e65a01c130fa6e22b2459b', }, { url: 'assets/app-logo.007611f1.svg', revision: null }, { url: 'assets/close.915249f6.svg', revision: null }, { url: 'assets/image1.47eb2262.png', revision: null }, { url: 'assets/image2.82abb677.png', revision: null }, { url: 'assets/image3.0727d240.png', revision: null }, { url: 'assets/image4.c21696be.png', revision: null }, { url: 'assets/image5.976b0ba1.png', revision: null }, { url: 'assets/index.0fb3162c.js', revision: null }, { url: 'assets/index.f0b36889.css', revision: null }, { url: 'assets/settings.e67704e2.svg', revision: null }, { url: 'assets/workbox-window.prod.es5.e0cc53cf.js', revision: null }, { url: 'favicon.ico', revision: '547587c645ecf0155439c8e0edb6cb3d' }, { url: 'index.html', revision: 'ecfa72ef5ede33cddcab4b29ddfff4ff' }, { url: 'logo.svg', revision: '40dcf9f191738beb353d7a53edb8abd9' }, { url: 'maskable-icon-512x512.png', revision: 'a51a4f0cc05f269554afef971b7f658d', }, { url: 'pwa-192x192.png', revision: '9397e91d5e3a42bfa03ce2d07f7e3171', }, { url: 'pwa-512x512.png', revision: '49e40aedc6b5cd06157f00d8c564e379', }, { url: 'pwa-64x64.png', revision: '160c4d06af493fa1cb62ae9f4258003b' }, { url: 'pwa-64x64.png', revision: '160c4d06af493fa1cb62ae9f4258003b' }, { url: 'pwa-192x192.png', revision: '9397e91d5e3a42bfa03ce2d07f7e3171', }, { url: 'pwa-512x512.png', revision: '49e40aedc6b5cd06157f00d8c564e379', }, { url: 'maskable-icon-512x512.png', revision: 'a51a4f0cc05f269554afef971b7f658d', }, { url: 'manifest.webmanifest', revision: 'f9addcd4a864ed3a97c677e5274540c8', }, ], {} ), ```


I don't think having duplicates is such a problem since they have the same revision, but still it's unclear to me what approach should I take considering:

a. It looks like the Static assets handling page is not accurate based on my tests b. Including assets manually through includeAssets helps on adding public files into the precache, but it won't help for other files c. The most accurate approach, which is using globPatterns is causing duplicate file revisions

Last but not least, I was hoping to develop my own Service Worker using injestManifest strategy instead of generateSW, which only requires me to change from workbox.globPatterns to injectManifest.globaPatterns. However, I'm facing the exact same issue having duplicate file revisions, so it's not up to the strategy I'm using.

Thanks in advance!


EDIT: I forgot to share the Dev Tools output that shows up all files just once (which is good!), so the issue would remain on the precache generation only, which seems like a minor thing.

Screenshot 2023-07-20 at 12 15 17

Omitted custom images and icons from the screenshot, leaving just manifest files.

userquin commented 1 year ago

@lgaspari weird, I have published the new docs for my vuetify nuxt module (VitePress) and the sw is fine: https://vuetify-nuxt-module.netlify.app/

I'll check running the examples in the vite-plugin-pwa repo.

are you using Vite or some meta framework (SvelteKit, Nuxt...)?

userquin commented 1 year ago

@lgaspari includeManifestIcons: false when including png extension, all pwa icons are included by default, I'll try to fix it, can you confirm it?

I guess we can improve this function https://github.com/vite-pwa/vite-plugin-pwa/blob/main/src/assets.ts#L47, called to include pwa icons and shorcuts icons

The logic here https://github.com/vite-pwa/vite-plugin-pwa/blob/main/src/assets.ts#L56, called from src/options.ts module

lgaspari commented 1 year ago

are you using Vite or some meta framework (SvelteKit, Nuxt...)?

Just plain Vite for now.

@lgaspari includeManifestIcons: false when including png extension, all pwa icons are included by default, I'll try to fix it, can you confirm it?

Actually, this made the trick! It looks like using both features together causes the duplicate file revision, so I could just do:

{
  ...

  // Don't include manifest icons in favor of `injectManifest.globPatterns`.
  includeManifestIcons: false,

  // Inject manifest options.
  injectManifest: {
    globPatterns: ['**/*.{js,css,html,ico,png,svg}'],
  },

  ...
}

I guess we can improve this function https://github.com/vite-pwa/vite-plugin-pwa/blob/main/src/assets.ts#L47, called to include pwa icons and shorcuts icons

That would be good, like either use just globPatterns or fallback to includeManifestIcons + includeAssets.

lgaspari commented 1 year ago

Yeah, I've been doing some extra runs on my end and that seems exactly what I needed for adding not only public/ files (from includeAssets option) but also any other asset found in the project (from workbox.globPatterns option) whilst avoiding duplicate file revision adding includeManifestIcons: false.

@userquin could you confirm this behavior below?

// meant for public/* files only
includeAssets: [
  // works
  'apple-touch-icon-180x180.png',
  'favicon.ico',
  'logo.svg',
  'robots.txt',

  // won't match src/assets/* files
  '**/*.png',
],
// meant for the whole project, including public/* files
workbox: {
  // will match most files
  globPatterns: ['**/*.{js,css,html,ico,png,svg}'],
},
userquin commented 1 year ago

No, workbox will use glogPatterns in the dist folder only. The options included in the pwa will generate the revision from the public folder, Vite will copy public folder after workbox build.

lgaspari commented 1 year ago

No, workbox will use glogPatterns in the dist folder only.

Right, I meant the dist/ folder, my bad.

The options included in the pwa will generate the revision from the public folder, Vite will copy public folder after workbox build.

Hmm, if Vite copies the public/ folder after workbox build, how is it possible to have those files listed in the precache then?

These are my runs:

Run 1

config: ``` includeAssets: [ 'apple-touch-icon-180x180.png', ], ``` output: ``` e.precacheAndRoute( [ { url: 'apple-touch-icon-180x180.png', revision: '9b7a985648e65a01c130fa6e22b2459b', }, ] ```

Run 2

config: ``` includeAssets: [ 'apple-touch-icon-180x180.png', ], workbox: { globPatterns: ['**/*.{js,css,html,ico,png,svg}'], }, ``` output: ``` e.precacheAndRoute( [ { url: 'apple-touch-icon-180x180.png', revision: '9b7a985648e65a01c130fa6e22b2459b', }, { url: 'apple-touch-icon-180x180.png', revision: '9b7a985648e65a01c130fa6e22b2459b', }, ] ```

Run 3

config: ``` workbox: { globPatterns: ['**/*.{js,css,html,ico,png,svg}'], }, ``` output: ``` e.precacheAndRoute( [ { url: 'apple-touch-icon-180x180.png', revision: '9b7a985648e65a01c130fa6e22b2459b', }, ] ```

The same would happen to every file listed in the includeAssets config (e.g. favicon.ico, logo.svg) that matches the globPatterns. In case of robots.txt, I'd keep it in the includeAssets array, but I could def add .txt to the glob pattern.

Let me know if you need a further example, I'm just trying to wrap my head around how it works to fine-tune the configuration based on that.


EDIT: I'm currently using Vite at version ^3.0.7 if that helps.

userquin commented 1 year ago

We include them using manifestEntries when listed in includeAssets and includeManifestIcon enabled

userquin commented 1 year ago

Check the assets module

lgaspari commented 1 year ago

Gotcha! I thought they were kind of exclusive at moment of writing my above comment without having double-checked the code as you pointed out.

The issue can be closed since the solution to my problem was given in https://github.com/vite-pwa/docs/issues/67#issuecomment-1644155534 by @userquin. Thanks a lot dude! 💯