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 VitePWA() and tanstackStart() both present.
This is likely because to vite-plugin-pwa not having proper support for the Vite 6 environment API. There is an open PR to solve this: https://github.com/vite-pwa/vite-plugin-pwa/pull/786, however the current state of this PR has the same issue as the stable version of the package.
No PWA/SW steps are ran in build:
but it works in the vite dev server:
Your Example Website or App
https://stackblitz.com/edit/github-djpcrmc9?file=src%2Frouter.tsx
Steps to Reproduce the Bug or Issue
npm installnpm run build- No PWA/SW steps are ran in build:
Expected behavior
- Build steps actually run during
vite build - Service worker gets built into tanstack start's
client-dist, so it can also get picked up by nitropublicAssets[] - Any script injection steps such as into also work(?)
Screenshots or Videos
No response
Platform
- Start Version: ^1.131.7
- OS: macOS, Stackblitz WebContainer
- Browser: Chrome
- Browser Version: 139.0.7258.66
- Bundler: Vite
- Bundler Version: ^6.3.5
Additional context
No response
+1
@f1shy-dev did you find any workaround?
@FatahChan For now you can try a few other more manual/involved things:
Try other plugins: https://serwist.pages.dev/docs/vite/getting-started (haven't tried myself, but somebody said it might work).
Or you can manually make a vite plugin-type thing which runs pwa-assets-generator and or creates a service worker:
//vite.config.ts, plugins section
{
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
},
// in my case, I made a script to generate just the SW, but you can also add assets etc
buildStart: () => workboxGenerate(),
},
//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() {
const clientDist = resolve(__dirname, '.tanstack/start/build/client-dist')
const swDest = resolve(clientDist, 'sw.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)`)
}
Then just register it with new Workbox or normal service workers on the client.
I tried https://serwist.pages.dev/docs/vite doesn't work, kinda make sense as it's a fork of VITE pwa
@FatahChan For now you can try a few other more manual/involved things:
Try other plugins: https://serwist.pages.dev/docs/vite/getting-started (haven't tried myself, but somebody said it might work).
Or you can manually make a vite plugin-type thing which runs
pwa-assets-generatorand or creates a service worker://vite.config.ts, plugins section { 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 }, // in my case, I made a script to generate just the SW, but you can also add assets etc buildStart: () => workboxGenerate(), }, //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() { const clientDist = resolve(__dirname, '.tanstack/start/build/client-dist') const swDest = resolve(clientDist, 'sw.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)) } Then just register it withnew Workboxor normal service workers on the client.
where is buildId defined? thanks
I tried https://serwist.pages.dev/docs/vite doesn't work, kinda make sense as it's a fork of VITE pwa
I use Tanstack Router with serwist successful - I am not sure about what exactly would need to be changed to make it start with Start - so I am curious about it as I soon want to migrate from Router to Start
@FatahChan buildId was just an optional thing I added in but i defined it via viteConfig.define
const config = defineConfig({
define: {
'window.BUILD_ID': `"${buildId}"`,
},
//...
Any news no this?My team needs to start a new project but don't want to use Nextjs 😅
Any news no this?My team needs to start a new project but don't want to use Nextjs 😅
If your website is SPA, then TanStack Router + Hono with hRPC) could do the job and pwa plugin works great with it.
Would love a timeline on this, if any.
FYI, I created a similar bug report in the Serwist repo b/c I'm experiencing the same issue there as well and can imagine that they have the same common ground b/c Serwist is forked from vite-plugin-pwa:
[Bug]: sw.js is not built in vite with Tanstack Start production build
+1