From 5a8f15c6c128ece4f40c39f0495423312360f5ae Mon Sep 17 00:00:00 2001 From: LinMoQC <2896311434@qq.com> Date: Sun, 26 Apr 2026 01:54:44 +0800 Subject: [PATCH] :ambulance: fix(web): harden docker production build --- apps/web/Dockerfile | 7 +++++++ apps/web/config/solid-js-web-shim.mjs | 2 +- apps/web/next.config.mjs | 23 ++++++++++++++--------- apps/web/src/app/providers.tsx | 12 +++++++++++- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/apps/web/Dockerfile b/apps/web/Dockerfile index 193852e..3a2e781 100644 --- a/apps/web/Dockerfile +++ b/apps/web/Dockerfile @@ -44,6 +44,13 @@ COPY packages/api-client ./packages/api-client COPY packages/types ./packages/types COPY packages/ui ./packages/ui +# Next 在解析 packages/* 源码里的二级依赖时会从仓库根继续向上查找 node_modules。 +# 为 builder 显式补根级 workspace 链接,避免仅在 apps/web/node_modules 下可见。 +RUN mkdir -p ./node_modules/@lyranote \ + && ln -sfn ../../packages/api-client ./node_modules/@lyranote/api-client \ + && ln -sfn ../../packages/types ./node_modules/@lyranote/types \ + && ln -sfn ../../packages/ui ./node_modules/@lyranote/ui + # 构建参数 ARG NEXT_PUBLIC_API_BASE_URL=/api/v1 ENV NEXT_PUBLIC_API_BASE_URL=${NEXT_PUBLIC_API_BASE_URL} diff --git a/apps/web/config/solid-js-web-shim.mjs b/apps/web/config/solid-js-web-shim.mjs index 3386a35..396a61e 100644 --- a/apps/web/config/solid-js-web-shim.mjs +++ b/apps/web/config/solid-js-web-shim.mjs @@ -1 +1 @@ -export * from "/Users/kaihuang/Desktop/graduation-project/LyraNote/node_modules/.pnpm/solid-js@1.9.12/node_modules/solid-js/web/dist/web.js"; +export * from "solid-js/web"; diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index 930cf17..81fc5e3 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -32,14 +32,17 @@ if (fs.existsSync(pnpmStore)) { } const solidWebShimPath = path.join(__configDir, "config/solid-js-web-shim.mjs"); +const shouldUseSolidWebShim = + process.env.NODE_ENV === "development" && Boolean(solidWebBrowserPath); -if (solidWebBrowserPath) { - // Re-export from the browser build which exports setStyleProperty. - fs.writeFileSync( - solidWebShimPath, - `export * from ${JSON.stringify(solidWebBrowserPath)};\n` - ); -} +// Only dev needs the browser build shim for Locator. Production should always +// stay host-agnostic so Docker/CI never bakes in a local absolute path. +fs.writeFileSync( + solidWebShimPath, + shouldUseSolidWebShim + ? `export * from ${JSON.stringify(solidWebBrowserPath)};\n` + : `export * from "solid-js/web";\n` +); const locatorTurbopackRules = createLocatorTurbopackRules({ dev: process.env.NODE_ENV === "development", @@ -66,8 +69,10 @@ const nextConfig = { config.module.rules.push(locatorRule); } - // Alias solid-js/web to the shim so @locator/runtime gets setStyleProperty. - config.resolve.alias["solid-js/web"] = solidWebShimPath; + if (dev) { + // Alias solid-js/web to the shim so @locator/runtime gets setStyleProperty. + config.resolve.alias["solid-js/web"] = solidWebShimPath; + } return config; }, diff --git a/apps/web/src/app/providers.tsx b/apps/web/src/app/providers.tsx index 6ef4e20..24144da 100644 --- a/apps/web/src/app/providers.tsx +++ b/apps/web/src/app/providers.tsx @@ -13,16 +13,26 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { LazyMotion, domAnimation } from "framer-motion"; +import dynamic from "next/dynamic"; import { AbstractIntlMessages, NextIntlClientProvider } from "next-intl"; import { useState } from "react"; import { Toaster } from "sileo"; import { AuthProvider } from "@/features/auth/auth-provider"; import { setI18nMessages } from "@/lib/i18n"; -import { LocatorDevtools } from "@/lib/locator-devtools"; import { ThemeProvider, type ColorTheme } from "@/lib/theme"; import { ThemePresetProvider, type ThemePreset } from "@/lib/theme-preset"; +const LocatorDevtools = + process.env.NODE_ENV === "development" + ? dynamic( + () => import("@/lib/locator-devtools").then((module) => module.LocatorDevtools), + { ssr: false } + ) + : function LocatorDevtoolsFallback() { + return null; + }; + interface ProvidersProps { children: React.ReactNode; messages: AbstractIntlMessages;