我有 NextJS 应用程序的 Kubernetes 部署,我想在开发模式下运行该应用程序,以便更新文件会导致应用程序立即热重载,特别是我想只更新“config”文件夹中的一些 JSON 文件。我创建了一个 docker 容器,它复制除“配置文件”之外的必要文件,配置文件使用 Kubernetes ConfigMaps 附加到容器,作为卷安装。
我在 Windows WSL2 上的 minikube 上运行。
当我第一次运行容器时,它工作正常,但如果我导航到某些页面或更改配置映射中的值,我会收到此错误(或使用不同文件的错误,如
PlanModel.config.json
):
> @ dev-base /usr/src/app
> next dev
▲ Next.js 14.2.3
- Local: http://localhost:3000
✓ Starting...
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out
if you'd not like to participate in this anonymous program, by visiting the following URL:https://nextjs.org/telemetry
✓ Ready in 3s
○ Compiling /middleware ...
✓ Compiled /middleware in 2.3s (216 modules) ○ Compiling / ...
Browserslist: caniuse-lite is outdated. Please run:
npx update-browserslist-db@latest
Why you should do it regularly: https://github.com/browserslist/update-db#readme
✓ Compiled / in 18.6s (4401 modules)
cookie is: undefined
GET / 200 in 19523ms
✓ Compiled in 1339ms (1847 modules)
cookie is: undefined
GET / 200 in 68ms
cookie is: undefined
GET / 200 in 46ms
cookie is: undefined
GET / 200 in 37ms
⨯ ./config/ai/..2024_09_30_15_42_23.830652425/actions.config.json
Module build failed: Error: ENOENT: no such file or directory, open '/usr/src/app/config/ai/..2024_09_30_15_42_23.830652425/actions.config.json'
Import trace for requested module:
./config/ai/..2024_09_30_15_42_23.830652425/actions.config.json
./lib/chat/actions.config.tsx
./lib/chat/actions.tsx
./app/(chat)/page.tsx
有时,应用程序不会立即收到此错误,而是继续工作,但没有热重载。
在这两种情况下,我都在容器中打开了一个 shell,并手动验证了文件是否存在且正确。
我注意到 Kubernetes 为 configmap 中的文件创建了符号链接。特别是,符号链接是这样的:
actions.config.json -> ..data/actions.config.json -> ..2024_09_30_15_42_23.830652425/actions.config.json
我发现 NextJS 在开发模式下跟踪符号链接存在问题,因为 webpack (https://github.com/vercel/next.js/issues/53175, https://github.com/webpack/手表包/拉/232)。我不知道如何解决这个问题。我想我可以使用不创建符号链接的不同 Kubernetes 方法(但我仍然需要可以轻松更新配置文件),或者解决这个 NextJS 问题。
我想构建一个平台,允许用户通过更改一些“配置文件”(实际上是 JSON 文件)来自定义 NextJS 应用程序。这些配置文件由 NextJS 应用程序(静态)导入,并确定应用程序的颜色、样式和行为。这样我的用户就可以访问显示以下内容的编辑器:
我没有创建一个与我已经创建的略有不同的新 NextJS 应用程序,并且为了允许实时更改,我只是决定在开发模式下运行它。
无论如何,“最终版本”和“预览版本”都必须大规模运行,我决定使用 kubernetes。我创建了一个 API,可以动态生成两个版本的 kubernetes 清单。
我遇到的问题是预览版本,我有这个缩短的示例文件:
apiVersion: v1
kind: Namespace
metadata:
labels:
app_id: myId
app_subdomain: testapp
name: myId
---
apiVersion: v1
kind: ConfigMap
metadata:
name: app-environment
namespace: myId
data:
# App configuration
APP_ID: myId
# Postgres database, MongoDB database, etc env variables
---
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app_id: myId
app_subdomain: testapp
name: app-config
namespace: myId
data:
theme.config.json: |
CONTENT
---
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app_id: myId
app_subdomain: testapp
name: app-config-ai
namespace: myId
data:
actions.config.json: |
CONTENT
---
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app_id: myId
app_subdomain: testapp
name: app-config-components
namespace: myId
data:
button-scroll-to-bottom.config.json: |
CONTENT
chat-history.config.json: |
CONTENT
chat-message-actions.config.json: |
CONTENT
---
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app_id: myId
app_subdomain: testapp
name: app-config-components-ui
namespace: myId
data:
sheet.config.json: |
CONTENT
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app_id: myId
app_subdomain: testapp
name: app
namespace: myId
spec:
replicas: 1
selector:
matchLabels:
app_id: myId
template:
metadata:
labels:
app_id: myId
app_subdomain: testapp
spec:
containers:
- name: nginx
image: my-nginx:latest
imagePullPolicy: Always
ports:
- containerPort: 80
- name: app
image: my-app-configurable:latest
imagePullPolicy: Always
envFrom:
- configMapRef:
name: app-environment
ports:
- containerPort: 3000
volumeMounts: # /usr/src/app/ is the root directory of the app in the container
- name: app-config
mountPath: /usr/src/app/config
- name: app-config-ai
mountPath: /usr/src/app/config/ai
- name: app-config-components
mountPath: /usr/src/app/config/components
- name: app-config-components-ui
mountPath: /usr/src/app/config/components/ui
volumes:
- name: app-config
configMap:
name: app-config
- name: app-config-ai
configMap:
name: app-config-ai
- name: app-config-components
configMap:
name: app-config-components
- name: app-config-components-ui
configMap:
name: app-config-components-ui
---
apiVersion: v1
kind: Service
metadata:
labels:
app_id: myId
app_subdomain: testapp
name: nginx-service
namespace: myId
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app_id: myId
---
apiVersion: v1
kind: Service
metadata:
labels:
app_id: myId
app_subdomain: testapp
name: app
namespace: myId
spec:
ports:
- port: 3000
protocol: TCP
targetPort: 3000
selector:
app_id: myId
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels:
app_id: myId
app_subdomain: testapp
name: nginx
namespace: myId
spec:
rules:
- host: testapp.zshape.ai
http:
paths:
- backend:
service:
name: nginx-service
port:
number: 80
path: /
pathType: Prefix
这是在我的 NextJS 应用程序中导入 JSON 文件的示例:
import rawConfig from '@/config/components/empty-screen.config.json'
interface ComponentConfig {
[key: string]: any
title?: string
description?: string
linkURL?: string
linkLabel?: string
}
const { title, description, linkURL, linkLabel }: ComponentConfig = rawConfig
export const emptyScreenConfig = {
title,
description,
linkURL,
linkLabel
}
然后导出的
emptyScreenConfig
会导入到应用程序的其他部分。
我通过使用
next dev --turbo
解决了这个问题,它使用 Turbopack 而不是 Webpack。就我而言,我使用金丝雀版本的next
和测试版next-auth
,因为当前稳定版本不支持某些功能。