feat: i18n PWA webmanifests (#805)
Co-authored-by: Daniel Roe <daniel@roe.dev>
This commit is contained in:
parent
18056038c7
commit
85ac005570
7 changed files with 190 additions and 73 deletions
|
@ -1,9 +1,10 @@
|
|||
import { defineNuxtModule } from '@nuxt/kit'
|
||||
import type { VitePWAOptions, VitePluginPWAAPI } from 'vite-plugin-pwa'
|
||||
import type { VitePluginPWAAPI } from 'vite-plugin-pwa'
|
||||
import { VitePWA } from 'vite-plugin-pwa'
|
||||
import type { Plugin } from 'vite'
|
||||
import type { VitePWANuxtOptions } from './types'
|
||||
import { configurePWAOptions } from './config'
|
||||
import { type LocalizedWebManifest, createI18n, pwaLocales } from './i18n'
|
||||
|
||||
export * from './types'
|
||||
export default defineNuxtModule<VitePWANuxtOptions>({
|
||||
|
@ -20,6 +21,7 @@ export default defineNuxtModule<VitePWANuxtOptions>({
|
|||
const resolveVitePluginPWAAPI = (): VitePluginPWAAPI | undefined => {
|
||||
return vitePwaClientPlugin?.api
|
||||
}
|
||||
let webmanifests: LocalizedWebManifest | undefined
|
||||
|
||||
// TODO: combine with configurePWAOptions?
|
||||
nuxt.hook('nitro:init', (nitro) => {
|
||||
|
@ -37,12 +39,55 @@ export default defineNuxtModule<VitePWANuxtOptions>({
|
|||
const plugin = viteInlineConfig.plugins.find(p => p && typeof p === 'object' && 'name' in p && p.name === 'vite-plugin-pwa')
|
||||
if (plugin)
|
||||
throw new Error('Remove vite-plugin-pwa plugin from Vite Plugins entry in Nuxt config file!')
|
||||
const resolvedOptions: Partial<VitePWAOptions> = {
|
||||
...options,
|
||||
manifest: options.manifest ? await options.manifest() : undefined,
|
||||
|
||||
webmanifests = await createI18n()
|
||||
const generateManifest = (locale: string) => {
|
||||
const manifest = webmanifests![locale]
|
||||
if (!manifest)
|
||||
throw new Error(`No webmanifest found for locale ${locale}`)
|
||||
return JSON.stringify(manifest)
|
||||
}
|
||||
configurePWAOptions(resolvedOptions, nuxt)
|
||||
const plugins = VitePWA(resolvedOptions)
|
||||
viteInlineConfig.plugins.push({
|
||||
name: 'elk:pwa:locales:build',
|
||||
apply: 'build',
|
||||
generateBundle(_, bundle) {
|
||||
if (options.disable || !bundle)
|
||||
return
|
||||
|
||||
Object.keys(webmanifests!).map(l => [l, `manifest-${l}.webmanifest`]).forEach(([l, fileName]) => {
|
||||
bundle[fileName] = {
|
||||
isAsset: true,
|
||||
type: 'asset',
|
||||
name: undefined,
|
||||
source: generateManifest(l),
|
||||
fileName,
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
viteInlineConfig.plugins.push({
|
||||
name: 'elk:pwa:locales:dev',
|
||||
apply: 'serve',
|
||||
configureServer(server) {
|
||||
const localeMatcher = new RegExp(`^${nuxt.options.app.baseURL}manifest-(.*).webmanifest$`)
|
||||
server.middlewares.use((req, res, next) => {
|
||||
const match = req.url?.match(localeMatcher)
|
||||
const entry = match && webmanifests![match[1]]
|
||||
if (entry) {
|
||||
res.statusCode = 200
|
||||
res.setHeader('Content-Type', 'application/manifest+json')
|
||||
res.write(JSON.stringify(entry), 'utf-8')
|
||||
res.end()
|
||||
}
|
||||
else {
|
||||
next()
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
configurePWAOptions(options, nuxt)
|
||||
const plugins = VitePWA(options)
|
||||
viteInlineConfig.plugins.push(plugins)
|
||||
if (isClient)
|
||||
vitePwaClientPlugin = plugins.find(p => p.name === 'vite-plugin-pwa') as Plugin
|
||||
|
@ -61,8 +106,17 @@ export default defineNuxtModule<VitePWANuxtOptions>({
|
|||
return
|
||||
|
||||
viteServer.middlewares.stack.push({ route: webManifest, handle: emptyHandle })
|
||||
if (webmanifests) {
|
||||
Object.keys(webmanifests).forEach((locale) => {
|
||||
viteServer.middlewares.stack.push({
|
||||
route: `${nuxt.options.app.baseURL}manifest-${locale}.webmanifest`,
|
||||
handle: emptyHandle,
|
||||
})
|
||||
})
|
||||
}
|
||||
viteServer.middlewares.stack.push({ route: devSw, handle: emptyHandle })
|
||||
})
|
||||
|
||||
if (!options.strategies || options.strategies === 'generateSW') {
|
||||
nuxt.hook('vite:serverCreated', (viteServer, { isServer }) => {
|
||||
if (isServer)
|
||||
|
@ -76,6 +130,16 @@ export default defineNuxtModule<VitePWANuxtOptions>({
|
|||
}
|
||||
}
|
||||
else {
|
||||
nuxt.hook('nitro:config', async (nitroConfig) => {
|
||||
nitroConfig.routeRules = nitroConfig.routeRules || {}
|
||||
for (const locale of pwaLocales) {
|
||||
nitroConfig.routeRules![`/manifest-${locale.code}.webmanifest`] = {
|
||||
headers: {
|
||||
'Content-Type': 'application/manifest+json',
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
nuxt.hook('nitro:init', (nitro) => {
|
||||
nitro.hooks.hook('rollup:before', async () => {
|
||||
await resolveVitePluginPWAAPI()?.generateSW()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue