diff --git a/Dockerfile b/Dockerfile index a6e91791..4a0ed96e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,10 @@ FROM base AS deps COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ RUN pnpm install --frozen-lockfile +FROM base AS prod-deps +COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ +RUN pnpm install --prod --frozen-lockfile + FROM base AS builder ARG NEXT_ENV_FILE=.env.local ENV CI=true @@ -40,56 +44,8 @@ RUN addgroup --system --gid 1001 nodejs \ COPY --from=builder /app/public ./public COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static - -RUN set -eux; \ - esbuild_pkg="$(find node_modules/.pnpm -path '*/node_modules/esbuild/package.json' -print -quit)"; \ - esbuild_binary_pkg="$(find node_modules/.pnpm -path '*/node_modules/@esbuild/linux-*/package.json' -print -quit)"; \ - idb_pkg="$(find node_modules/.pnpm -path '*/node_modules/idb/package.json' -print -quit)"; \ - serwist_pkg="$(find node_modules/.pnpm -path '*/node_modules/serwist/package.json' -print -quit)"; \ - serwist_turbopack_pkg="$(find node_modules/.pnpm -path '*/node_modules/@serwist/turbopack/package.json' -print -quit)"; \ - serwist_utils_pkg="$(find node_modules/.pnpm -path '*/node_modules/@serwist/utils/package.json' -print -quit)"; \ - if [ -n "$esbuild_pkg" ] && [ -n "$esbuild_binary_pkg" ]; then \ - esbuild_pkg="${esbuild_pkg%/package.json}"; \ - esbuild_binary_pkg="${esbuild_binary_pkg%/package.json}"; \ - esbuild_binary_name="$(basename "$esbuild_binary_pkg")"; \ - rm -rf node_modules/esbuild; \ - ln -s "/app/$esbuild_pkg" node_modules/esbuild; \ - mkdir -p node_modules/@esbuild "$esbuild_pkg/node_modules/@esbuild"; \ - rm -rf "node_modules/@esbuild/$esbuild_binary_name" "$esbuild_pkg/node_modules/@esbuild/$esbuild_binary_name"; \ - ln -s "/app/$esbuild_binary_pkg" "node_modules/@esbuild/$esbuild_binary_name"; \ - ln -s "/app/$esbuild_binary_pkg" "$esbuild_pkg/node_modules/@esbuild/$esbuild_binary_name"; \ - fi; \ - if [ -n "$serwist_pkg" ]; then \ - serwist_pkg="${serwist_pkg%/package.json}"; \ - rm -rf node_modules/serwist; \ - ln -s "/app/$serwist_pkg" node_modules/serwist; \ - fi; \ - if [ -n "$idb_pkg" ]; then \ - idb_pkg="${idb_pkg%/package.json}"; \ - rm -rf node_modules/idb; \ - ln -s "/app/$idb_pkg" node_modules/idb; \ - if [ -n "$serwist_pkg" ]; then \ - rm -rf "$serwist_pkg/node_modules/idb"; \ - ln -s "/app/$idb_pkg" "$serwist_pkg/node_modules/idb"; \ - fi; \ - fi; \ - if [ -n "$serwist_turbopack_pkg" ]; then \ - serwist_turbopack_pkg="${serwist_turbopack_pkg%/package.json}"; \ - mkdir -p node_modules/@serwist; \ - rm -rf node_modules/@serwist/turbopack; \ - ln -s "/app/$serwist_turbopack_pkg" node_modules/@serwist/turbopack; \ - fi; \ - if [ -n "$serwist_utils_pkg" ]; then \ - serwist_utils_pkg="${serwist_utils_pkg%/package.json}"; \ - mkdir -p node_modules/@serwist; \ - rm -rf node_modules/@serwist/utils; \ - ln -s "/app/$serwist_utils_pkg" node_modules/@serwist/utils; \ - if [ -n "$serwist_pkg" ]; then \ - mkdir -p "$serwist_pkg/node_modules/@serwist"; \ - rm -rf "$serwist_pkg/node_modules/@serwist/utils"; \ - ln -s "/app/$serwist_utils_pkg" "$serwist_pkg/node_modules/@serwist/utils"; \ - fi; \ - fi +COPY --from=prod-deps --chown=nextjs:nodejs /app/node_modules ./node_modules +COPY --from=builder --chown=nextjs:nodejs /app/src/app/sw.ts ./src/app/sw.ts USER nextjs EXPOSE 3000 diff --git a/next.config.ts b/next.config.ts index a9023142..9ac37e24 100644 --- a/next.config.ts +++ b/next.config.ts @@ -9,7 +9,7 @@ import { withSerwist } from "@serwist/turbopack"; * * 容器化部署模型:`output: "standalone"` + Docker Compose。 * - `pnpm build` 产出 .next/standalone、.next/static、public。 - * - Dockerfile 运行 `node server.js`,不再依赖 `next start` 和完整 node_modules。 + * - Dockerfile 运行 `node server.js`,并保留生产依赖以支持 Serwist 运行时生成 SW。 */ const nextConfig: NextConfig = { output: "standalone", @@ -17,16 +17,6 @@ const nextConfig: NextConfig = { // 关闭静态优化以规避 16.2.7 global-error prerender bug staticGenerationRetryCount: 0, }, - outputFileTracingIncludes: { - "/serwist/*": [ - "./src/app/sw.ts", - "./node_modules/.pnpm/@serwist+*/node_modules/@serwist/**/*", - "./node_modules/.pnpm/idb@*/node_modules/idb/**/*", - "./node_modules/.pnpm/serwist@*/node_modules/serwist/**/*", - "./node_modules/.pnpm/esbuild@*/node_modules/esbuild/**/*", - "./node_modules/.pnpm/@esbuild+linux-*@*/node_modules/@esbuild/linux-*/**/*", - ], - }, images: { remotePatterns: [ { diff --git a/package.json b/package.json index ca5c8237..465b66fd 100644 --- a/package.json +++ b/package.json @@ -26,11 +26,13 @@ "dependencies": { "@fingerprintjs/fingerprintjs": "^5.2.0", "@sentry/nextjs": "^10.61.0", + "@serwist/turbopack": "^9.0.0", "@stripe/react-stripe-js": "^6.6.0", "@stripe/stripe-js": "^9.8.0", "@xstate/react": "^5", "classnames": "^2.5.1", "dexie": "^4.4.3", + "esbuild": "^0.25.0", "lottie-react": "^2.4.1", "lucide-react": "^1.18.0", "next": "16.2.7", @@ -40,6 +42,7 @@ "react": "19.2.4", "react-dom": "19.2.4", "react-icons": "^5.6.0", + "serwist": "^9.0.0", "ua-parser-js": "^2.0.10", "unstorage": "^1.17.5", "xstate": "^5", @@ -47,7 +50,6 @@ }, "devDependencies": { "@playwright/test": "^1.61.1", - "@serwist/turbopack": "^9.0.0", "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", @@ -55,11 +57,9 @@ "@vitest/coverage-v8": "^4.1.8", "@vitest/ui": "^4.1.8", "barrelsby": "^2.8.1", - "esbuild": "^0.25.0", "eslint": "^9", "eslint-config-next": "16.2.7", "jsdom": "^29.1.1", - "serwist": "^9.0.0", "tailwindcss": "^4", "typescript": "^5", "vitest": "^4.1.8" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 85c8b02d..e8f8887b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@sentry/nextjs': specifier: ^10.61.0 version: 10.61.0(@opentelemetry/core@2.8.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.8.0(@opentelemetry/api@1.9.1))(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(webpack@5.108.0(esbuild@0.25.12)) + '@serwist/turbopack': + specifier: ^9.0.0 + version: 9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3) '@stripe/react-stripe-js': specifier: ^6.6.0 version: 6.6.0(@stripe/stripe-js@9.8.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -29,6 +32,9 @@ importers: dexie: specifier: ^4.4.3 version: 4.4.3 + esbuild: + specifier: ^0.25.0 + version: 0.25.12 lottie-react: specifier: ^2.4.1 version: 2.4.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -56,6 +62,9 @@ importers: react-icons: specifier: ^5.6.0 version: 5.6.0(react@19.2.4) + serwist: + specifier: ^9.0.0 + version: 9.5.11(browserslist@4.28.2)(typescript@5.9.3) ua-parser-js: specifier: ^2.0.10 version: 2.0.10 @@ -72,9 +81,6 @@ importers: '@playwright/test': specifier: ^1.61.1 version: 1.61.1 - '@serwist/turbopack': - specifier: ^9.0.0 - version: 9.5.11(esbuild@0.25.12)(next@16.2.7(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.61.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4)(typescript@5.9.3) '@tailwindcss/postcss': specifier: ^4 version: 4.3.0 @@ -96,9 +102,6 @@ importers: barrelsby: specifier: ^2.8.1 version: 2.8.1 - esbuild: - specifier: ^0.25.0 - version: 0.25.12 eslint: specifier: ^9 version: 9.39.4(jiti@2.7.0) @@ -108,9 +111,6 @@ importers: jsdom: specifier: ^29.1.1 version: 29.1.1 - serwist: - specifier: ^9.0.0 - version: 9.5.11(browserslist@4.28.2)(typescript@5.9.3) tailwindcss: specifier: ^4 version: 4.3.0