From c6c4d52556919be93a9adb899369f9617b8479aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20S=C3=A1nchez?= Date: Tue, 30 May 2023 19:38:24 +0200 Subject: [PATCH] fix(pwa): pwa icons in dev and build (#2137) --- modules/pwa/index.ts | 58 ++++++++++++++++++++++++++++++++++++++------ package.json | 2 +- pnpm-lock.yaml | 34 +++++++++++++------------- 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/modules/pwa/index.ts b/modules/pwa/index.ts index 5b4cf3d8..72a348c1 100644 --- a/modules/pwa/index.ts +++ b/modules/pwa/index.ts @@ -1,14 +1,27 @@ -import { mkdir, writeFile } from 'node:fs/promises' +import { mkdir, readFile, writeFile } from 'node:fs/promises' +import type { Buffer } from 'node:buffer' +import { dirname } from 'node:path' +import { fileURLToPath } from 'node:url' import { addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit' import type { VitePluginPWAAPI } from 'vite-plugin-pwa' import { VitePWA } from 'vite-plugin-pwa' import type { Plugin } from 'vite' -import { join } from 'pathe' +import { join, resolve } from 'pathe' import type { VitePWANuxtOptions } from './types' import { configurePWAOptions } from './config' import { type LocalizedWebManifest, createI18n, pwaLocales } from './i18n' export * from './types' + +interface PwaDevIcon { + src: string + type: string +} + +interface ResolvedPwaDevIcon extends PwaDevIcon { + data: Promise +} + export default defineNuxtModule({ meta: { name: 'elk-pwa', @@ -88,12 +101,33 @@ export default defineNuxtModule({ }) } viteInlineConfig.plugins.push({ - name: 'elk:pwa:locales:dev', + name: 'elk:pwa:dev', apply: 'serve', configureServer(server) { + const icons: PwaDevIcon[] = webmanifests?.['en-US']?.icons as any + const mappedIcons: PwaDevIcon[] = [ + ...icons.map(({ src, type }) => ({ src, type })), + { src: 'favicon.ico', type: 'image/x-icon' }, + { src: 'apple-touch-icon.png', type: 'image/png' }, + { src: 'logo.svg', type: 'image/svg+xml' }, + ] + + const folder = dirname(fileURLToPath(import.meta.url)) + const useIcons = mappedIcons.reduce((acc, icon) => { + icon.src = `${nuxt.options.app.baseURL}${icon.src}` + acc[icon.src] = { + ...icon, + data: readFile(resolve(join(folder, '../../public-dev', icon.src))), + } + return acc + }, >{}) const localeMatcher = new RegExp(`^${nuxt.options.app.baseURL}manifest-(.*).webmanifest$`) - server.middlewares.use((req, res, next) => { - const match = req.url?.match(localeMatcher) + server.middlewares.use(async (req, res, next) => { + const url = req.url + if (!url) + return next() + + const match = url.match(localeMatcher) const entry = match && webmanifests![match[1]] if (entry) { res.statusCode = 200 @@ -101,10 +135,18 @@ export default defineNuxtModule({ res.setHeader('Cache-Control', 'public, max-age=0, must-revalidate') res.write(JSON.stringify(entry), 'utf-8') res.end() + return } - else { - next() - } + + const icon = useIcons[url] + if (!icon) + return next() + + res.statusCode = 200 + res.setHeader('Content-Type', icon.type) + res.setHeader('Cache-Control', 'public, max-age=0, must-revalidate') + res.write(await icon.data) + res.end() }) }, }) diff --git a/package.json b/package.json index b068632f..717cd57a 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,7 @@ "ufo": "^1.1.2", "ultrahtml": "^1.2.0", "unimport": "^3.0.7", - "vite-plugin-pwa": "^0.15.1", + "vite-plugin-pwa": "^0.15.2", "vue-advanced-cropper": "^2.8.8", "vue-virtual-scroller": "2.0.0-beta.8", "workbox-build": "^6.5.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b5ce68e8..fbf5dbb2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -205,8 +205,8 @@ importers: specifier: ^3.0.7 version: 3.0.7(rollup@2.79.1) vite-plugin-pwa: - specifier: ^0.15.1 - version: 0.15.1(vite@4.3.9)(workbox-build@6.5.4)(workbox-window@6.5.4) + specifier: ^0.15.2 + version: 0.15.2(vite@4.3.9)(workbox-build@6.5.4)(workbox-window@6.5.4) vue-advanced-cropper: specifier: ^2.8.8 version: 2.8.8(vue@3.3.4) @@ -1994,8 +1994,8 @@ packages: vue-i18n: optional: true dependencies: - '@intlify/message-compiler': 9.3.0-beta.17 - '@intlify/shared': 9.3.0-beta.17 + '@intlify/message-compiler': 9.3.0-beta.18 + '@intlify/shared': 9.3.0-beta.18 jsonc-eslint-parser: 1.4.1 source-map: 0.6.1 vue-i18n: 9.3.0-beta.16(vue@3.3.4) @@ -2014,8 +2014,8 @@ packages: vue-i18n: optional: true dependencies: - '@intlify/message-compiler': 9.3.0-beta.17 - '@intlify/shared': 9.3.0-beta.17 + '@intlify/message-compiler': 9.3.0-beta.18 + '@intlify/shared': 9.3.0-beta.18 jsonc-eslint-parser: 1.4.1 source-map: 0.6.1 vue-i18n: 9.3.0-beta.16(vue@3.3.4) @@ -2047,11 +2047,11 @@ packages: source-map: 0.6.1 dev: false - /@intlify/message-compiler@9.3.0-beta.17: - resolution: {integrity: sha512-i7hvVIRk1Ax2uKa9xLRJCT57to08OhFMhFXXjWN07rmx5pWQYQ23MfX1xgggv9drnWTNhqEiD+u4EJeHoS5+Ww==} - engines: {node: '>= 14'} + /@intlify/message-compiler@9.3.0-beta.18: + resolution: {integrity: sha512-pN/MOrKjWHJWSRxt0kEdqPcPqHV1pJlJXmvrX8Lv12HRWmiGo1w4lVBz5POS1sych+gk/DK4RvdZZJTmFwrXGA==} + engines: {node: '>= 16'} dependencies: - '@intlify/shared': 9.3.0-beta.17 + '@intlify/shared': 9.3.0-beta.18 source-map: 0.6.1 dev: false @@ -2060,9 +2060,9 @@ packages: engines: {node: '>= 14'} dev: false - /@intlify/shared@9.3.0-beta.17: - resolution: {integrity: sha512-mscf7RQsUTOil35jTij4KGW1RC9SWQjYScwLxP53Ns6g24iEd5HN7ksbt9O6FvTmlQuX77u+MXpBdfJsGqizLQ==} - engines: {node: '>= 14'} + /@intlify/shared@9.3.0-beta.18: + resolution: {integrity: sha512-Z+XZ1YQL/ZudauayZFNbW2PDf4ac7UBs3PCRsBRb2UcAgat3jN9IZYNDyluQBx4Gmko02kvqc8kC5uJmMlGhmQ==} + engines: {node: '>= 16'} dev: false /@intlify/unplugin-vue-i18n@0.8.1(vue-i18n@9.3.0-beta.16): @@ -2081,7 +2081,7 @@ packages: optional: true dependencies: '@intlify/bundle-utils': 3.4.0(vue-i18n@9.3.0-beta.16) - '@intlify/shared': 9.3.0-beta.17 + '@intlify/shared': 9.3.0-beta.18 '@rollup/pluginutils': 4.2.1 '@vue/compiler-sfc': 3.3.4 debug: 4.3.4 @@ -13898,8 +13898,8 @@ packages: - supports-color dev: false - /vite-plugin-pwa@0.15.1(vite@4.3.9)(workbox-build@6.5.4)(workbox-window@6.5.4): - resolution: {integrity: sha512-lJVzEYda/Y9AfwxFzX0rV+QCQ2+WdBoEGtR1RBZKWxvrJ4NWEH1VZaHOMyzvRiYhWQsi7aFhewsp1CDvN/R1Og==} + /vite-plugin-pwa@0.15.2(vite@4.3.9)(workbox-build@6.5.4)(workbox-window@6.5.4): + resolution: {integrity: sha512-l1srtaad5NMNrAtAuub6ArTYG5Ci9AwofXXQ6IsbpCMYQ/0HUndwI7RB2x95+1UBFm7VGttQtT7woBlVnNhBRw==} peerDependencies: vite: ^3.1.0 || ^4.0.0 workbox-build: ^6.5.4 @@ -14195,7 +14195,7 @@ packages: vue-router: optional: true dependencies: - '@intlify/shared': 9.3.0-beta.17 + '@intlify/shared': 9.3.0-beta.18 '@intlify/vue-i18n-bridge': 0.8.0(vue-i18n@9.3.0-beta.16) '@intlify/vue-router-bridge': 0.8.0(vue-router@4.2.2)(vue@3.3.4) ufo: 1.1.2