英文:
Next.JS v13 in Docker does not respect path alias but works locally
问题
以下是要翻译的部分:
错误:
> [builder 6/6] RUN pnpm run build:
#25 0.534
#25 0.534 > p-stack-fs@0.1.0 build /app
#25 0.534 > next build
#25 0.534
#25 0.940 - 警告:您已启用了next.config.js中的实验性功能(instrumentationHook)。
#25 0.941 - 警告:实验性功能不受semver支持,可能导致意外或破坏的应用程序行为。自行承担风险使用。
#25 0.941
#25 1.010 - 信息 正在创建优化的生产构建...
#25 10.94 编译失败。
#25 10.94
#25 10.95 ./src/app/layout.tsx
#25 10.95 模块未找到:无法解析'~/components/NavBar'
#25 10.95
#25 10.95 https://nextjs.org/docs/messages/module-not-found
#25 10.95
#25 10.95 ./src/app/layout.tsx
#25 10.95 模块未找到:无法解析'~/styles/css'
#25 10.95
#25 10.95 https://nextjs.org/docs/messages/module-not-found
#25 10.95
#25 10.95
#25 10.95 > 构建失败,因为webpack错误
#25 11.09 ELIFECYCLE 命令以退出码1失败。
你可以看到文件存在且命名正确的部分在这里:
Dockerfile:
ARG ALPINE_VERSION=3.17
FROM node:20-alpine AS base
# 仅在需要时安装依赖项
FROM base AS deps
# 查看https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine 以了解为什么可能需要libc6-compat。
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
COPY panda.config.ts ./
RUN npm i -g pnpm && pnpm i --prod --frozen-lockfile
# 仅在需要时重新构建源代码
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Panda在“prepare”命令中构建,在“install”后运行,因此我们在这里将其复制过来以进行构建
# COPY --from=deps /app/src/styles/ ./src/styles/
RUN ["chmod", "+x", "./docker-entrypoint.sh"]
# Next.js会收集关于一般用法的完全匿名的遥测数据。
# 了解更多信息:https://nextjs.org/telemetry
# 在构建过程中禁用遥测时,请取消下面一行的注释。
ENV NEXT_TELEMETRY_DISABLED 1
RUN npm i -g pnpm
RUN pnpm run build
# 生产镜像,复制所有文件并运行next
FROM alpine:${ALPINE_VERSION} AS runner
WORKDIR /app
# 在运行时禁用遥测时,请取消下面一行的注释。
ENV NEXT_TELEMETRY_DISABLED 1
RUN apk add --no-cache --update nodejs
# 使用Go二进制文件获取AWS SSM参数,减小镜像大小
# 注意:如果不使用USER nextjs,则可能会出现“8: not found”错误,与ca-certificates有关
RUN apk update && apk add --no-cache ca-certificates && update-ca-certificates
RUN wget https://github.com/pthieu/go-aws-get-parameter/raw/master/ssm_get_parameter
RUN ["chmod", "+x", "./ssm_get_parameter"]
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# 自动利用输出跟踪以减小镜像大小
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/static ./.next/static
# COPY --from=builder /app/src/db/migrations ./migrations
COPY --from=builder --chown=nextjs:nodejs /app/docker-entrypoint.sh ./
USER nextjs
EXPOSE 80
ENV PORT 80
ENTRYPOINT [ "sh", "docker-entrypoint.sh" ]
CMD ["node", "server.js"]
# 用于调试,保持容器处于活动状态
# CMD ["tail", "-f", "/dev/null"]
请注意,Dockerfile和错误消息中可能包含的HTML字符实体已被保留,因为它们是代码的一部分。
英文:
I had a working docker build and when I put in absolute paths with a path alias, it suddenly started complaining module not found, can't resolve 'ComponentName'
It will fail at the pnpm run build
step, but when I run it locally, it works fine.
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"baseUrl": ".",
"paths": {
"~/*": [
"./src/*"
]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}
The file causing the error:
import { Providers } from './providers';
import NavBar from '~/components/NavBar';
import { css } from '~/styles/css';
import './global.css';
export const metadata = {
title: 'p-stack-fs',
description: 'A boilerplate for TypeScript, Next.js, and PostgreSQL',
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<Providers>
<div className={css({ minH: '100vh' })}>
<NavBar />
{children}
</div>
</Providers>
</body>
</html>
);
Error:
> [builder 6/6] RUN pnpm run build:
#25 0.534
#25 0.534 > p-stack-fs@0.1.0 build /app
#25 0.534 > next build
#25 0.534
#25 0.940 - warn You have enabled experimental feature (instrumentationHook) in next.config.js.
#25 0.941 - warn Experimental features are not covered by semver, and may cause unexpected or broken application behavior. Use at your own risk.
#25 0.941
#25 1.010 - info Creating an optimized production build...
#25 10.94 Failed to compile.
#25 10.94
#25 10.95 ./src/app/layout.tsx
#25 10.95 Module not found: Can't resolve '~/components/NavBar'
#25 10.95
#25 10.95 https://nextjs.org/docs/messages/module-not-found
#25 10.95
#25 10.95 ./src/app/layout.tsx
#25 10.95 Module not found: Can't resolve '~/styles/css'
#25 10.95
#25 10.95 https://nextjs.org/docs/messages/module-not-found
#25 10.95
#25 10.95
#25 10.95 > Build failed because of webpack errors
#25 11.09 ELIFECYCLE Command failed with exit code 1.
------
executor failed running [/bin/sh -c pnpm run build]: exit code: 1
You can see the files exist and are named properly here:
FWIW, here's my Dockerfile
ARG ALPINE_VERSION=3.17
FROM node:20-alpine AS base
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
COPY panda.config.ts ./
RUN npm i -g pnpm && pnpm i --prod --frozen-lockfile
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Panda is built in the `prepare` command, which runs after
# `install`, so we copy it over here for building
# COPY --from=deps /app/src/styles/ ./src/styles/
RUN ["chmod", "+x", "./docker-entrypoint.sh"]
# Next.js collects completely anonymous telemetry data about general usage.
# Learn more here: https://nextjs.org/telemetry
# Uncomment the following line in case you want to disable telemetry during the build.
ENV NEXT_TELEMETRY_DISABLED 1
RUN npm i -g pnpm
RUN pnpm run build
# Production image, copy all the files and run next
FROM alpine:${ALPINE_VERSION} AS runner
WORKDIR /app
# Uncomment the following line in case you want to disable telemetry during runtime.
ENV NEXT_TELEMETRY_DISABLED 1
RUN apk add --no-cache --update nodejs
# Get AWS SSM Params using a Go binary, reduces image size
# Note: this might get a "8: not found" error if not using the USER nextjs, has
# to do with something with the ca-certificates
RUN apk update && apk add --no-cache ca-certificates && update-ca-certificates
RUN wget https://github.com/pthieu/go-aws-get-parameter/raw/master/ssm_get_parameter
RUN ["chmod", "+x", "./ssm_get_parameter"]
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/static ./.next/static
# COPY --from=builder /app/src/db/migrations ./migrations
COPY --from=builder --chown=nextjs:nodejs /app/docker-entrypoint.sh ./
USER nextjs
EXPOSE 80
ENV PORT 80
ENTRYPOINT [ "sh", "docker-entrypoint.sh" ]
CMD ["node", "server.js"]
# For debugging, keeps container alive
# CMD ["tail", "-f", "/dev/null"]
答案1
得分: 2
Found the issue.
问题已找到。
The solution was to update next.config.js
to set the path alias in webpack. This should be the same as your tsconfig.json
.
解决方案是更新 next.config.js
来在 webpack 中设置路径别名。这应该与你的 tsconfig.json
相同。
const nextConfig = {
output: 'standalone',
webpack: (config, { isServer }) => {
config.resolve.alias['~'] = path.join(__dirname, 'src');
return config;
},
};
这是我的假设:在 Next.js 13 中,他们转向了 turbopack,但仍然使用 Webpack 作为打包工具。Webpack 运行的阶段与 TS 编译阶段不同,因此它不会考虑 tsconfig.json
。
Here's my hypothesis: in Next.js 13, they moved to turbopack but still use Webpack as a bundler. Webpack runs at a different phase than the TS compilation phase, so it doesn't take into account tsconfig.json
.
这是我的假设:在 Next.js 13 中,他们转向了 turbopack,但仍然使用 Webpack 作为打包工具。Webpack 运行的阶段与 TS 编译阶段不同,因此它不会考虑 tsconfig.json
。
英文:
Found the issue.
The solution was to update next.config.js
to set the path alias in webpack. This should be the same as your tsconfig.json
.
const nextConfig = {
output: 'standalone',
webpack: (config, { isServer }) => {
config.resolve.alias['~'] = path.join(__dirname, 'src');
return config;
},
};
Here's my hypothesis: in Next.js 13, they moved to turbopack but still use Webpack as a bundler. Webpack runs at a different phase than the TS compilation phase, so it doesn't take into account tsconfig.json
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论