Docker 中的 Next.JS v13 不考虑路径别名,但在本地工作

PGT*_*PGT 7 typescript docker reactjs dockerfile next.js

我有一个正在运行的 docker 版本,当我输入带有路径别名的绝对路径时,它突然开始抱怨module not found, can\'t resolve \'ComponentName\'

\n

它将失败于pnpm run build,但是当我在本地运行它时,它工作正常。

\n

tsconfig.json

\n
{\n  "compilerOptions": {\n    "target": "es5",\n    "lib": [\n      "dom",\n      "dom.iterable",\n      "esnext"\n    ],\n    "allowJs": true,\n    "skipLibCheck": true,\n    "strict": true,\n    "forceConsistentCasingInFileNames": true,\n    "noEmit": true,\n    "esModuleInterop": true,\n    "module": "esnext",\n    "moduleResolution": "node",\n    "resolveJsonModule": true,\n    "isolatedModules": true,\n    "jsx": "preserve",\n    "incremental": true,\n    "plugins": [\n      {\n        "name": "next"\n      }\n    ],\n    "baseUrl": ".",\n    "paths": {\n      "~/*": [\n        "./src/*"\n      ]\n    }\n  },\n  "include": [\n    "next-env.d.ts",\n    "**/*.ts",\n    "**/*.tsx",\n    ".next/types/**/*.ts"\n  ],\n  "exclude": [\n    "node_modules"\n  ]\n}\n
Run Code Online (Sandbox Code Playgroud)\n

导致错误的文件:

\n
import { Providers } from \'./providers\';\nimport NavBar from \'~/components/NavBar\';\nimport { css } from \'~/styles/css\';\n\nimport \'./global.css\';\n\nexport const metadata = {\n  title: \'p-stack-fs\',\n  description: \'A boilerplate for TypeScript, Next.js, and PostgreSQL\',\n};\n\nexport default function RootLayout({\n  children,\n}: {\n  children: React.ReactNode;\n}) {\n  return (\n    <html lang="en">\n      <body>\n        <Providers>\n          <div className={css({ minH: \'100vh\' })}>\n            <NavBar />\n            {children}\n          </div>\n        </Providers>\n      </body>\n    </html>\n  );\n
Run Code Online (Sandbox Code Playgroud)\n

错误:

\n
 > [builder 6/6] RUN pnpm run build:\n#25 0.534\n#25 0.534 > p-stack-fs@0.1.0 build /app\n#25 0.534 > next build\n#25 0.534\n#25 0.940 - warn You have enabled experimental feature (instrumentationHook) in next.config.js.\n#25 0.941 - warn Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use at your own risk.\n#25 0.941\n#25 1.010 - info Creating an optimized production build...\n#25 10.94 Failed to compile.\n#25 10.94\n#25 10.95 ./src/app/layout.tsx\n#25 10.95 Module not found: Can\'t resolve \'~/components/NavBar\'\n#25 10.95\n#25 10.95 https://nextjs.org/docs/messages/module-not-found\n#25 10.95\n#25 10.95 ./src/app/layout.tsx\n#25 10.95 Module not found: Can\'t resolve \'~/styles/css\'\n#25 10.95\n#25 10.95 https://nextjs.org/docs/messages/module-not-found\n#25 10.95\n#25 10.95\n#25 10.95 > Build failed because of webpack errors\n#25 11.09 \xe2\x80\x89ELIFECYCLE\xe2\x80\x89 Command failed with exit code 1.\n------\nexecutor failed running [/bin/sh -c pnpm run build]: exit code: 1\n
Run Code Online (Sandbox Code Playgroud)\n

您可以在此处看到文件存在并正确命名:

\n

在此输入图像描述

\n

FWIW,这是我的 Dockerfile

\n
ARG ALPINE_VERSION=3.17\n\nFROM node:20-alpine AS base\n\n# Install dependencies only when needed\nFROM base AS deps\n# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.\nRUN apk add --no-cache libc6-compat\nWORKDIR /app\n\nCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./\nCOPY panda.config.ts ./\n\nRUN npm i -g pnpm && pnpm i --prod --frozen-lockfile\n\n# Rebuild the source code only when needed\nFROM base AS builder\nWORKDIR /app\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY . .\n# Panda is built in the `prepare` command, which runs after\n# `install`, so we copy it over here for building\n# COPY --from=deps /app/src/styles/ ./src/styles/\n\nRUN ["chmod", "+x", "./docker-entrypoint.sh"]\n\n# Next.js collects completely anonymous telemetry data about general usage.\n# Learn more here: https://nextjs.org/telemetry\n# Uncomment the following line in case you want to disable telemetry during the build.\nENV NEXT_TELEMETRY_DISABLED 1\n\nRUN npm i -g pnpm\nRUN pnpm run build\n\n# Production image, copy all the files and run next\nFROM alpine:${ALPINE_VERSION} AS runner\n\nWORKDIR /app\n\n# Uncomment the following line in case you want to disable telemetry during runtime.\nENV NEXT_TELEMETRY_DISABLED 1\n\nRUN apk add --no-cache --update nodejs\n# Get AWS SSM Params using a Go binary, reduces image size\n# Note: this might get a "8: not found" error if not using the USER nextjs, has\n# to do with something with the ca-certificates\nRUN apk update && apk add --no-cache ca-certificates && update-ca-certificates\nRUN wget https://github.com/pthieu/go-aws-get-parameter/raw/master/ssm_get_parameter\nRUN ["chmod", "+x", "./ssm_get_parameter"]\n\nRUN addgroup --system --gid 1001 nodejs\nRUN adduser --system --uid 1001 nextjs\n\n# Automatically leverage output traces to reduce image size\n# https://nextjs.org/docs/advanced-features/output-file-tracing\nCOPY --from=builder /app/.next/standalone ./\nCOPY --from=builder /app/public ./public\nCOPY --from=builder /app/.next/static ./.next/static\n# COPY --from=builder /app/src/db/migrations ./migrations\n\nCOPY --from=builder --chown=nextjs:nodejs /app/docker-entrypoint.sh ./\n\nUSER nextjs\n\nEXPOSE 80\n\nENV PORT 80\n\nENTRYPOINT [ "sh", "docker-entrypoint.sh" ]\nCMD ["node", "server.js"]\n# For debugging, keeps container alive\n# CMD ["tail", "-f", "/dev/null"]\n
Run Code Online (Sandbox Code Playgroud)\n

PGT*_*PGT 11

发现问题了。

解决方案是更新next.config.js以在 webpack 中设置路径别名。这应该和你的一样tsconfig.json

const nextConfig = {
  output: 'standalone',
  webpack: (config, { isServer }) => {
    config.resolve.alias['~'] = path.join(__dirname, 'src');
    return config;
  },
};
Run Code Online (Sandbox Code Playgroud)

我的假设是:在 Next.js 13 中,他们转向了 Turbopack,但仍然使用 Webpack 作为捆绑器。Webpack 运行在与 TS 编译阶段不同的阶段,因此它不考虑tsconfig.json.

  • 我疯狂地试图弄清楚为什么它会在本地构建而不是在 Docker 中构建。这也为我解决了这个问题 - 非常感谢!对于其他遇到此问题的人,不要忘记 `const path = require('path')` (2认同)