This commit is contained in:
parent
d61a94d66a
commit
87ec871a4b
|
|
@ -1,36 +1,49 @@
|
||||||
// app/_runtime-env-provider.tsx
|
// app/_runtime-env-provider.tsx ← 文件放 app 根,保证是 Server 组件
|
||||||
import { headers } from "next/headers"
|
import { headers } from "next/headers" // ① 仅在服务器端可调用
|
||||||
import { useServerInsertedHTML } from "next/navigation"
|
import { useServerInsertedHTML } from "next/navigation" // ② 往最终 HTML 插入标签
|
||||||
import React from "react"
|
import React from "react"
|
||||||
|
|
||||||
export function RuntimeEnvProvider({
|
// ------------------- 带全链路调试日志的版本 -------------------
|
||||||
children,
|
export function RuntimeEnvProvider({ children }: { children: React.ReactNode }) {
|
||||||
}: {
|
/* ──────────────── 1. 解析协议 ──────────────── */
|
||||||
children: React.ReactNode
|
const h = headers() // <-- Node 边界:读取当前请求头
|
||||||
}) {
|
console.log("[RuntimeEnv] Raw headers:", Object.fromEntries(h.entries()))
|
||||||
/* 1. 协议 */
|
|
||||||
const h = headers()
|
|
||||||
const proto =
|
const proto =
|
||||||
h.get("x-forwarded-proto") ??
|
h.get("x-forwarded-proto") ?? // 走 Nginx / 反代时最可靠
|
||||||
(h.get("host")?.includes(":443") ? "https" : "http")
|
(h.get("host")?.includes(":443") ? "https" : "http")// 没有反代时根据端口猜
|
||||||
|
console.log("[RuntimeEnv] Resolved protocol:", proto)
|
||||||
|
|
||||||
/* 2. 主机(域名或 IP),剥离掉可能附带的端口 */
|
/* ──────────────── 2. 解析主机名 ──────────────── */
|
||||||
const rawHost = h.get("x-forwarded-host") ?? h.get("host")!
|
const rawHost = h.get("x-forwarded-host") ?? h.get("host")!
|
||||||
const hostname = rawHost.split(",")[0].split(":")[0] // 去掉逗号和端口
|
console.log("[RuntimeEnv] rawHost :", rawHost)
|
||||||
|
|
||||||
/* 3. 端口固定 8000 */
|
// 多层反代时 x-forwarded-host 可能是 "a.com, b.com"
|
||||||
|
// host 可能附带端口,须砍掉
|
||||||
|
const hostname = rawHost.split(",")[0].split(":")[0].trim()
|
||||||
|
console.log("[RuntimeEnv] hostname :", hostname)
|
||||||
|
|
||||||
|
/* ──────────────── 3. 拼最终 URL (端口固定 8000) ──────────────── */
|
||||||
const supabaseUrl = `${proto}://${hostname}:8000`
|
const supabaseUrl = `${proto}://${hostname}:8000`
|
||||||
|
console.log("[RuntimeEnv] supabaseUrl to inject:", supabaseUrl)
|
||||||
|
|
||||||
/* 4. 注入行内脚本 */
|
/* ──────────────── 4. 把脚本塞进 HTML ──────────────── */
|
||||||
useServerInsertedHTML(() => (
|
useServerInsertedHTML(() => {
|
||||||
<script
|
// 这一段在 React 把 HTML flush 给客户端之前执行一次
|
||||||
dangerouslySetInnerHTML={{
|
console.log("[RuntimeEnv] <script> tag inserted into HTML")
|
||||||
__html: `window.RUNTIME_ENV={SUPABASE_URL:${JSON.stringify(
|
|
||||||
supabaseUrl,
|
|
||||||
)}};`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))
|
|
||||||
|
|
||||||
return <>{children}</>
|
return (
|
||||||
|
<script
|
||||||
|
// 行内脚本:window.RUNTIME_ENV.SUPABASE_URL = "<url>"
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `window.RUNTIME_ENV = { SUPABASE_URL: ${JSON.stringify(
|
||||||
|
supabaseUrl,
|
||||||
|
)} };`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
/* ──────────────── 5. 渲染子节点 ──────────────── */
|
||||||
|
return <>{children}</> // Provider 本身不渲染 UI,只负责注入脚本
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue