You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
问题原因
  1. 客户端直接运行服务器端SDK:node-appwrite是Appwrite的服务器端SDK,不能在浏览器环境中执行。你在客户端组件(如PatientForm.tsx的onSubmit)中直接调用createUser,导致SDK在浏览器中运行时无法正确构造请求URL,同时还会暴露敏感的API_KEY,存在严重安全风险。
  2. 环境变量加载问题:客户端环境中无法正确读取服务器端环境变量,即使替换为实际值能临时运行,本质是错误地将服务器端逻辑放在客户端执行。
解决方法

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 23:47:04