T
TanStack2w ago
extended-salmon

vite-pwa plugin does not work in production builds

dev-sw.js works, but the core issue is that sw.js doesn't get built in prod output. is that possible that rollup might be causing the issue? if so, how to ignore that during the build. here's my repo with a workaround: https://github.com/kulterryan/tanstack-start-pwa
GitHub
GitHub - kulterryan/tanstack-start-pwa
Contribute to kulterryan/tanstack-start-pwa development by creating an account on GitHub.
24 Replies
stormy-gold
stormy-gold2w ago
from my (and gpt5's) investigation i believe vite-plugin-pwa doesn't work[1] due to the way it detects the server/client vite environment, doesn't seem to be properly fixed for multi-environment and even when I manually edited the package, couldn't figure out a proper way to get the worker to build somewhere other than dist/sw.js[2] [1]: "doesn't work" meaning that the plugin is seemingly not executed when running vite build with VitePWA() and tanstackStart() both present. as soon as you comment out the tanstackStart() plugin, the service worker gets generated to dist/sw.js and the assets generator runs if configured. which convinced me it was some environment detection/compatability issue [2]: this might just be due to my inexperience with configuring vite, and I didn't want to use a copy script. either way the ideal behaviour is that the sw gets built into tanstack start's client-dist, so it can also get picked up by nitro publicAssets[]
stormy-gold
stormy-gold2w ago
https://github.com/vite-pwa/vite-plugin-pwa/blob/4385f0a7f03b628ca0d635c07042a1031631ffb4/src/plugins/build.ts#L44 this.environment.config.consumer might be required rather than just checking for PWAPluginContext.viteConfig.build.ssr (not too sure)
GitHub
vite-plugin-pwa/src/plugins/build.ts at 4385f0a7f03b628ca0d635c0704...
Zero-config PWA for Vite. Contribute to vite-pwa/vite-plugin-pwa development by creating an account on GitHub.
stormy-gold
stormy-gold2w ago
my temporary solution was a bit different i ended up making a custom script using esbuild and workbox injectManifest, which runs through a vite plugin after client build, but before server (so it gets copied to nitro static assets)
//workbox-generate.ts
import { injectManifest } from 'workbox-build'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { build } from 'esbuild'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

export async function workboxGenerate(buildId: string) {
const clientDist = resolve(__dirname, '.tanstack/start/build/client-dist')
const swDest = resolve(clientDist, 'sw.js')
const swImplDest = resolve(clientDist, 'sw.module.js')

// sw.module includes exports so the browser doesn't refetch workbox when comparing sw.js versions
await build({
entryPoints: [resolve(__dirname, 'src/sw.module.ts')],
bundle: true,
outfile: swImplDest,
format: 'iife',
target: 'es2020',
minify: true,
define: {
'import.meta.env.DEV': 'false'
}
})

// includes importScripts(sw.module.js)
await build({
entryPoints: [resolve(__dirname, 'src/sw.ts')],
bundle: true,
outfile: swDest,
format: 'esm',
target: 'es2020',
minify: true,
define: {
'import.meta.env.DEV': 'false',
'self.__WB_BUILD_ID': `"${buildId}"`
}
})

// could have used generateSW and skipped the esbuild stages, I just needed more customisability
const { count, warnings, size } = await injectManifest({
swSrc: swDest,
swDest: swDest,
globDirectory: clientDist,
globPatterns: [
'**/*.{js,css,html,svg,png,ico,webmanifest,json}',
],
});

if (warnings.length) {
console.warn('[workbox] warnings:', warnings)
}
console.log(`[workbox] generated sw.js with ${count} precached files (${(size/1024).toFixed(1)} KiB)`)
}
//workbox-generate.ts
import { injectManifest } from 'workbox-build'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import { build } from 'esbuild'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

export async function workboxGenerate(buildId: string) {
const clientDist = resolve(__dirname, '.tanstack/start/build/client-dist')
const swDest = resolve(clientDist, 'sw.js')
const swImplDest = resolve(clientDist, 'sw.module.js')

// sw.module includes exports so the browser doesn't refetch workbox when comparing sw.js versions
await build({
entryPoints: [resolve(__dirname, 'src/sw.module.ts')],
bundle: true,
outfile: swImplDest,
format: 'iife',
target: 'es2020',
minify: true,
define: {
'import.meta.env.DEV': 'false'
}
})

// includes importScripts(sw.module.js)
await build({
entryPoints: [resolve(__dirname, 'src/sw.ts')],
bundle: true,
outfile: swDest,
format: 'esm',
target: 'es2020',
minify: true,
define: {
'import.meta.env.DEV': 'false',
'self.__WB_BUILD_ID': `"${buildId}"`
}
})

// could have used generateSW and skipped the esbuild stages, I just needed more customisability
const { count, warnings, size } = await injectManifest({
swSrc: swDest,
swDest: swDest,
globDirectory: clientDist,
globPatterns: [
'**/*.{js,css,html,svg,png,ico,webmanifest,json}',
],
});

if (warnings.length) {
console.warn('[workbox] warnings:', warnings)
}
console.log(`[workbox] generated sw.js with ${count} precached files (${(size/1024).toFixed(1)} KiB)`)
}
vite plugin:
{
name: "workbox",
applyToEnvironment(e) {
return e.name === "ssr"; // runs after client is done generating, but before the nitro server copies publicAssets[] so that injectManifest can glob on static assets properly
},
buildStart: () => workboxGenerate(buildId),
},
{
name: "workbox",
applyToEnvironment(e) {
return e.name === "ssr"; // runs after client is done generating, but before the nitro server copies publicAssets[] so that injectManifest can glob on static assets properly
},
buildStart: () => workboxGenerate(buildId),
},
and then just loaded it with workbox-window in __root.tsx but generally PWA support and also the pwa plugin need some work it seems
optimistic-gold
optimistic-gold2w ago
is the pwa vite plugin supporting vite's env api?
stormy-gold
stormy-gold2w ago
i don't think so
optimistic-gold
optimistic-gold2w ago
start is fully based on the env api. so would need that pwa plugin to support that most likely
stormy-gold
stormy-gold2w ago
oh looks like there is a PR
stormy-gold
stormy-gold2w ago
GitHub
feat!: add Vite 6 Environment API support by userquin · Pull Reque...
Description 2024-11-15: this PR only tested with VanillaJS/TypeScript via test:vite-ecosystem-ci script, rn cannot be tested with lib frameworks, Vite ecosystem-ci is failing for vue and svelte (p...
optimistic-gold
optimistic-gold2w ago
nice
stormy-gold
stormy-gold2w ago
hm
No description
optimistic-gold
optimistic-gold2w ago
can you test the pkr-new preview build?
stormy-gold
stormy-gold2w ago
sure, gimme a sec
optimistic-gold
optimistic-gold2w ago
this might still need some work but it would be good to know the state of it
stormy-gold
stormy-gold2w ago
looks like a similiar situation dev-sw.js works in dev server but no pwa/sw steps are ran in build
stormy-gold
stormy-gold2w ago
No description
stormy-gold
stormy-gold2w ago
working in dev though
No description
optimistic-gold
optimistic-gold2w ago
can you please check whether we have an open issue about this already on github? if yes, please add your findings there, otherwise create a new one.
stormy-gold
stormy-gold2w ago
i believe there isn't
optimistic-gold
optimistic-gold2w ago
i expect the prod issue to be resolvable with vite 7 as it adds a new buildApp hook for the env api which the plugin should register to build its own env. we should be able to upstream this to the pwa plugin then
stormy-gold
stormy-gold2w ago
just to doublecheck, it is the router repo right (possibly silly question)
optimistic-gold
optimistic-gold2w ago
yes router repo
stormy-gold
stormy-gold2w ago
GitHub
vite-plugin-pwa incompatible with tanstack start production builds ...
Which project does this relate to? Start Describe the bug vite-plugin-pwa's build steps (generate assets, generate serviceworker bundle) are seemingly not executed when running vite build with ...
extended-salmon
extended-salmonOP2w ago
Found this for PWA, might be helpful. https://serwist.pages.dev/docs/vite/getting-started
Getting started - @serwist/vite - Serwist
A Swiss Army knife for service workers.
plain-purple
plain-purple6d ago
I modified the Astro intergration vite-pwa has and it works like a charm, even though it's not clean

Did you find this page helpful?