fix(tauri): skip runtime-config.js injection in static export (#4332)

The Tauri build uses `output: 'export'`, so the dynamic `/runtime-config.js`
route handler is never emitted. Requesting it returns the SPA fallback HTML
and crashes with `Unexpected token '<'`. Gate the script tag on
`NEXT_PUBLIC_APP_PLATFORM === 'web'`; Tauri consumers already fall back to
the `NEXT_PUBLIC_*` envs baked in at build time.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin
2026-05-28 10:14:47 +08:00
committed by GitHub
parent 4e01e13ee7
commit 381eed21cc
2 changed files with 16 additions and 2 deletions
+10 -1
View File
@@ -123,6 +123,13 @@ const devHmrPatchScript = `(${patchTauriHmrWebSocket.toString()})(${JSON.stringi
process.env['TAURI_DEV_HOST'],
)});`;
// `/runtime-config.js` is a dynamic route handler that only exists in the
// web/Docker build. The Tauri build is statically exported (`output:
// 'export'`), so the file isn't emitted — the request would return the SPA
// fallback HTML and crash with `Unexpected token '<'`. All runtime-config
// consumers fall back to `NEXT_PUBLIC_*` envs baked at build time on Tauri.
const shouldInjectRuntimeConfig = process.env['NEXT_PUBLIC_APP_PLATFORM'] === 'web';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html
@@ -130,7 +137,9 @@ export default function RootLayout({ children }: { children: React.ReactNode })
className={process.env['NEXT_PUBLIC_APP_PLATFORM'] === 'tauri' ? 'edge-to-edge' : ''}
>
<head>
<Script src='/runtime-config.js' strategy='beforeInteractive' />
{shouldInjectRuntimeConfig ? (
<Script src='/runtime-config.js' strategy='beforeInteractive' />
) : null}
{shouldInjectDevHmrPatch ? (
<script dangerouslySetInnerHTML={{ __html: devHmrPatchScript }} />
) : null}
+6 -1
View File
@@ -1,6 +1,9 @@
import { Html, Head, Main, NextScript } from 'next/document';
import Script from 'next/script';
// Only the web/Docker build serves `/runtime-config.js`. See app/layout.tsx.
const shouldInjectRuntimeConfig = process.env['NEXT_PUBLIC_APP_PLATFORM'] === 'web';
export default function Document() {
return (
<Html lang='en'>
@@ -8,7 +11,9 @@ export default function Document() {
<body>
{/* beforeInteractive must live in _document (not _app) to guarantee the
script runs before any client-side module evaluation. */}
<Script src='/runtime-config.js' strategy='beforeInteractive' />
{shouldInjectRuntimeConfig ? (
<Script src='/runtime-config.js' strategy='beforeInteractive' />
) : null}
<Main />
<NextScript />
</body>