Next.js集成Appwrite报错TypeError: Failed to construct 'URL'求助
问题描述
跟随JS Mastery的YouTube教程开发基于Next.js和Appwrite的医疗应用时,已在.env.local中配置Appwrite云的API密钥等参数,但运行项目时出现以下错误:
TypeError: Failed to construct 'URL': Invalid URL at Users.create (users.mjs:77:17) at createUser (patient.actions.ts:6:37) at onSubmit (PatientForm.tsx:43:42) at eval (index.esm.mjs:2256:23)
将代码中的环境变量替换为.env中的实际值后,项目可正常运行。
相关代码与配置如下:
创建用户逻辑
import { ID, Query } from "node-appwrite" import { users } from "../appwrite.config" export const createUser = async (user: CreateUserParams) => { try { const newUser = await users.create( ID.unique(), user.email, user.phone, undefined, user.name ) console.log(newUser) } catch(error: any) { if (error && error?.code === 409) { const documents = await users.list([ Query.equal('email', [user.email]) ]) return documents?.users[0] } else { console.log(error) } } }
Appwrite配置
import * as sdk from "node-appwrite"; export const { NEXT_PUBLIC_ENDPOINT: ENDPOINT, PROJECT_ID, API_KEY, DATABASE_ID, PATIENT_COLLECTION_ID, DOCTOR_COLLECTION_ID, APPOINTMENT_COLLECTION_ID, NEXT_PUBLIC_BUCKET_ID: BUCKET_ID, } = process.env; const client = new sdk.Client(); client.setEndpoint(ENDPOINT!).setProject(PROJECT_ID!).setKey(API_KEY!); export const databases = new sdk.Databases(client); export const users = new sdk.Users(client); export const messaging = new sdk.Messaging(client); export const storage = new sdk.Storage(client);
.env.local配置
PROJECT_ID=************ API_KEY=************************************ DATABASE_ID=************ PATIENT_COLLECTION_ID=************ DOCTOR_COLLECTION_ID=************ APPOINTMENT_COLLECTION_ID=************ NEXT_PUBLIC_BUCKET_ID=************ NEXT_PUBLIC_ENDPOINT=https://cloud.appwrite.io/v1
问题原因
- 客户端直接运行服务器端SDK:
node-appwrite是Appwrite的服务器端SDK,不能在浏览器环境中执行。你在客户端组件(如PatientForm.tsx的onSubmit)中直接调用createUser,导致SDK在浏览器中运行时无法正确构造请求URL,同时还会暴露敏感的API_KEY,存在严重安全风险。 - 环境变量加载问题:客户端环境中无法正确读取服务器端环境变量,即使替换为实际值能临时运行,本质是错误地将服务器端逻辑放在客户端执行。
解决方法
1. 将用户创建逻辑改为服务器Action
在patient.actions.ts顶部添加'use server'指令,标记代码在服务器端运行:
'use server'; import { ID, Query } from "node-appwrite" import { users } from "../appwrite.config" export const createUser = async (user: CreateUserParams) => { try { const newUser = await users.create( ID.unique(), user.email, user.phone, undefined, user.name ) console.log(newUser) return newUser; } catch(error: any) { if (error && error?.code === 409) { const documents = await users.list([ Query.equal('email', [user.email]) ]) return documents?.users[0] } else { console.error(error) throw error; } } }
2. 调整环境变量配置
服务器端使用的变量无需添加NEXT_PUBLIC_前缀(仅客户端需要的变量才加),修改.env.local:
# 服务器端变量(不暴露给客户端) PROJECT_ID=************ API_KEY=************************************ DATABASE_ID=************ PATIENT_COLLECTION_ID=************ DOCTOR_COLLECTION_ID=************ APPOINTMENT_COLLECTION_ID=************ # 客户端变量(暴露给浏览器) NEXT_PUBLIC_ENDPOINT=https://cloud.appwrite.io/v1 NEXT_PUBLIC_BUCKET_ID=************
3. 修正Appwrite配置文件
确保配置文件能正确读取服务器端变量,并添加变量存在性校验:
import * as sdk from "node-appwrite"; export const { NEXT_PUBLIC_ENDPOINT, PROJECT_ID, API_KEY, DATABASE_ID, PATIENT_COLLECTION_ID, DOCTOR_COLLECTION_ID, APPOINTMENT_COLLECTION_ID, NEXT_PUBLIC_BUCKET_ID, } = process.env; const client = new sdk.Client(); // 校验必填变量是否存在 if (!PROJECT_ID || !API_KEY || !NEXT_PUBLIC_ENDPOINT) { throw new Error("缺少必要的Appwrite环境变量"); } client.setEndpoint(NEXT_PUBLIC_ENDPOINT!).setProject(PROJECT_ID!).setKey(API_KEY!); export const databases = new sdk.Databases(client); export const users = new sdk.Users(client); export const messaging = new sdk.Messaging(client); export const storage = new sdk.Storage(client);
4. 客户端调用服务器Action
在客户端组件中正常调用服务器Action即可:
'use client'; import { createUser } from '@/app/actions/patient.actions'; // ... const onSubmit = async (data: CreateUserParams) => { try { const user = await createUser(data); // 处理成功逻辑 } catch (error) { // 处理错误逻辑 } };
5. 重启开发服务器
修改.env.local后,必须重启Next.js开发服务器才能加载新的环境变量。
内容的提问来源于stack exchange,提问作者Kavin Bharathi
相关产品推荐
相关产品推荐

