Skip to content
This page has been auto-translated and may contain errors.View in English

本地运行代码 ​

这个页面会帮助你在自己的电脑上运行提取的 Intro to AI Agents 项目:一个与 AI 提供商通信的 Express 服务器,以及一个在浏览器中打开的 Vite 前端。课程后续的内容不依赖于此,而且无论你是否这样做,Scrimba 版本都会继续正常运行。

首先需要准备什么 ​

支持的 Node.js LTS 版本。 推荐使用 Node 24,Node 22 也可以用。检查一下你已经安装的版本:

bash
$ node --version
v24.18.0

如果显示"command not found",从 nodejs.org 安装标记为 LTS 的版本。

npm。 Node 自带 npm,Scrimba 的下载项目都是 npm 项目。检查一下 npm 是否可用:

bash
$ npm --version
11.18.0
Juno首先需要准备什么 从 nodejs.org 安装标记为 LTS 的 Node.js 版本,你就会获得 npm,所以上面的两个命令都应该打印出版本号。

如果其中任何一个显示"command not found",问题就是这个,安装 Node 可以一次性解决两个问题。

Juno首先需要准备什么 Node 24 是推荐版本,Node 22 也能用。项目使用 Node 内置的加载器加载 .env 文件,如果加载器缺失,会停止并显示一条提及 Node 20.12 的信息。

那个版本号只是说明信息的含义;它不是建议你安装的版本。Node 20 已经不再获得安全更新,所以如果你管理多个 Node 版本,就把这个项目设置为 24 然后继续。

Juno首先需要准备什么 生成的 environment.js 从 node:process 导入 loadEnvFile。在没有这个功能的 Node 上,守卫会抛出"Local environment loading requires Node.js 20.12 or newer.",而不是继续使用空的变量。

这很重要,因为另一种方式会误导你:空变量到达提供商时会被视为缺少密钥,症状会指向你的凭证而不是你的运行时。在这里,这个信息总是意味着改变 Node,而不是 .env。

打开项目文件夹 ​

在包含 package.json 的提取文件夹中打开终端:

bash
$ cd path-to-your-downloaded-project

看一下里面有什么。具体的文件因课程而异。package.json 总是存在的,里面列出了项目期望的命令;应用课程还包括 server.js、environment.js 和 vite.config.js 这样的文件。

Juno打开项目文件夹 用 cd 进入包含 package.json 的提取文件夹。这个页面上的每个命令都从这里运行。

当命令说某个文件缺失时,在改变其他任何东西之前,先检查你的终端当前在哪个文件夹。

Juno打开项目文件夹 运行任何东西之前,先打开 package.json。它的 scripts 块告诉你这个项目期望的命令,这比瞎猜要好得多。

看到 server.js 和 vite.config.js 并排存在也很有意义:这个项目同时运行一个 Express 服务器和一个 Vite 开发服务器,这样可以使 API 密钥远离页面。

Juno打开项目文件夹 课程源代码使用 pnpm,但 Scrimba 打包步骤会移除 pnpm 锁定和工作区文件,并将脚本重写为调用 npm,所以 start 变成 concurrently --raw "npm run --silent server" "npm run --silent client"。

直接使用下载的包并通过 npm 工作,而不是在周围重新创建源工作区。

安装并运行 ​

在 Scrimba 上,AI_URL、AI_KEY 和 AI_MODEL 存储在你的账户设置中,Scrimba 将它们注入到运行的项目中。这就是为什么浏览器版本中没有 .env 文件:在那里不需要它,而且在共享编辑器中保存密钥也是一个不好的做法。在你的电脑上,没有什么注入它们,所以 .env 文件就负责这个工作。

安装下载项目的依赖,然后启动它:

bash
$ npm install
$ npm start

第一次运行时,environment.js 会注意到必需的值缺失,在 package.json 旁边创建 .env,并停止 Express 服务器,显示包含以下行的消息:

text
Missing environment variables: AI_KEY, AI_MODEL, AI_URL.
Created .env with the required variable names. Complete it, then restart the app.

Vite 可能继续运行,所以在编辑新文件之前,按 Ctrl+C 停止它。生成的 .env 每个变量有一个空行,最后有一个注释的端口行:

dotenv
AI_KEY=
AI_MODEL=
AI_URL=
# PORT=3001

在每个 = 后面填入你的真实值,= 周围没有空格:

dotenv
AI_KEY=your-api-key-here
AI_MODEL=gpt-5.4-nano
AI_URL=https://api.openai.com/v1
# PORT=3001

这些是你在 Scrimba 的环境变量中使用的相同值。如果你需要再次获取它们,参见提供商设置。保留 # PORT=3001 这一行不变;项目使用端口 3001,除非你改变它。

后续的一些课程会向生成的文件中添加可选行,如 GITHUB_TOKEN=。服务器可以在没有这些行的情况下启动,并打印 ○ Optional environment not configured: GITHUB_TOKEN。没有 GitHub 令牌的情况下,GitHub 请求会使用较低的匿名速率限制。

永远不要提交你的 .env 文件

如果你把这个项目放在 Git 中,在第一次提交之前,在项目文件夹中的 .gitignore 里列出 .env。一个被推送到公共仓库的密钥是一个你必须撤销的密钥,自动爬虫会在几分钟内找到它。node_modules 也属于那里,因为它很大,npm install 会重新构建它:

txt
.env
node_modules

.env.example 是安全提交的文件,因为它包含占位符文本而不是你的密钥。Git 手册在忽略文件和最佳实践中介绍了更广泛的习惯。

保存 .env 后重新启动项目:

bash
$ npm start

Node 通过生成的 environment.js 加载文件。下载的 vite.config.js 调用 Vite 的 loadEnv,所以 Vite 在配置浏览器到服务器的代理时读取相同的文件。你不需要安装 dotenv 或编辑 server.js。

npm start 同时运行两个进程:保存你的 API 密钥并发起模型请求的 Express 服务器,以及提供前端的 Vite 开发服务器。你会在同一个终端看到来自两者的交错输出。环境检查成功和两个地址行的出现意味着它工作了:

text
Environment check:
✓ AI_KEY: configured
✓ AI_MODEL: gpt-5.4-nano
✓ AI_URL: https://api.openai.com/v1
OpenSwap server running at http://localhost:3001

  VITE v6.4.3  ready in 214 ms

  ➜  Local:   http://localhost:5173/

打开 Vite URL,而不是 Express 那个。前端是你交互的东西,它在幕后将 API 调用转发给 Express。

用 Ctrl+C 停止两者。

Juno安装并运行 运行一次 npm install,然后 npm start。第一次启动会创建 .env 并停止;按 Ctrl+C,填入你在 Scrimba 上使用的三个值,保存,然后再次启动。

当你看到环境检查的勾号和 Vite 地址时,打开那个地址。如果你使用 Git,在第一次提交之前创建 .gitignore,而不是之后。

Juno安装并运行 在 Scrimba 之外改变的唯一一件事是没有什么供应环境值,所以 .env 做一个以前不可见的工作。生成的 environment.js 用正确的名字创建文件并为 Express 加载它。

Vite 是一个单独的进程,可能会在第一次服务器失败后存活,这就是为什么你用 Ctrl+C 停止整个命令,然后在填入值后重新启动它。

Juno安装并运行 服务器通过 Node 内置的 loadEnvFile 加载密钥,而 Vite 仅在配置代理时调用 loadEnv。浏览器不接收密钥:它调用相对 /api 路由,Express 拥有提供商请求。

如果密钥确实到达仓库,在后来的提交中删除文件不会将其移除;它在历史中保持可读。在提供商处撤销它并发出新密钥是唯一真正的修复,这就是为什么 .gitignore 要放在最前面。

两个服务器如何相互找到 ​

你的前端代码调用 /api/swaps 这样的路径,没有主机名和端口。这之所以能工作,是因为 vite.config.js 中的代理:

js
import { defineConfig, loadEnv } from "vite";

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), "");
  const port = env.PORT || process.env.PORT || 3001;

  return {
    server: {
      hmr: false,
      watch: {
        ignored: ["**/*"],
      },
      proxy: {
        "/api": {
          target: `http://localhost:${port}`,
        },
      },
    },
  };
});

任何以 /api 开头的东西都会被转发到 Express。这就是为什么前端代码永远不需要知道后端在哪个端口上,也是为什么在开发中你不会遇到跨来源错误。

课程游乐场有意禁用 Vite 的自动重新加载行为,所以保存不会在你处理课程时擦除当前输出。当你想加载一个改变时,手动刷新浏览器。

Juno两个服务器如何相互找到 在浏览器中使用 Vite 地址,通常是 http://localhost:5173。以 /api 开头的调用会为你转发到 Express 服务器,所以你永远不会直接打开端口 3001。

编辑文件后,自己刷新浏览器;页面不会自动重新加载。

Juno两个服务器如何相互找到 Vite 的代理将相对 /api 请求映射到 .env 中的端口上的 Express,或在没有设置端口时映射到 3001。这使前端与后端端口无关,并避免了开发期间需要单独的跨来源设置。
Juno两个服务器如何相互找到 两个进程都从相同的 .env 独立解析 PORT:Node 在 Express 监听之前,Vite 在构建代理目标时。一条注释的 # PORT 行算作未设置,所以两者一起回退到 3001。

HMR 和文件监视有意被禁用,所以改变需要手动刷新浏览器。

当端口 3001 被占用时 ​

如果你的电脑上已经有别的东西使用端口 3001,Express 会启动失败,显示 EADDRINUSE。打开 .env,移除末尾 # PORT=3001 行的 #(如果这一行不存在,就添加它),然后改变这个数字:

dotenv
PORT=3101

然后用 Ctrl+C 停止项目,再次运行 npm start。这是你需要的唯一改变。server.js 读取 PORT 来决定在哪里监听,Vite 在配置其代理之前读取相同的值。

前端端口的行为不同。如果 5173 被占用,Vite 会移动到下一个可用端口并打印那个地址,所以读取 Local: 行,而不是从记忆中输入 localhost:5173。要自己选择前端端口,把它传给 Vite:

bash
$ npm run client -- --port 5180

光秃秃的 -- 告诉 npm 把它之后的标志传给 Vite,而不是作为 npm 选项处理。

Juno当端口 3001 被占用时 如果你看到 EADDRINUSE,打开 .env,把 # PORT=3001 改为 PORT=3101(# 要去掉),然后重启。前端会自动获取新的后端端口。

对于前端本身,只需打开 Vite 打印的任何地址。

Juno当端口 3001 被占用时 Express 和 Vite 代理都从相同的 .env 读取 PORT,所以改变那一个值会使它们保持同步。

Vite 前端有自己的端口:当那个被占用时它从 5173 向上走,npm run client -- --port 5180 直接设置它。

Juno当端口 3001 被占用时 Express 没有回退:在一个被占用的端口上 listen 会抛出错误,所以后端需要显式的 PORT。这个项目中的 Vite 没有设置 strictPort,所以它自己向上移动。

后端端口改变属于 .env,前端端口改变属于 Vite CLI 参数,代理跟随后端因为它读取相同的值。没有什么硬编码目标。

如果某些东西不工作 ​

EADDRINUSE 意味着端口已被占用。参见上面的部分。

Missing environment variables: 后面跟着名字意味着 .env 中的这些行仍然是空的,或者文件没有被保存。填入它们并重新启动。

缺少凭证或身份验证错误 意味着 AI_KEY 没有到达代码,或者提供商拒绝了它。检查你的文件是否被命名为 .env 而不是 .env.txt,它是否与 package.json 在同一文件夹中,值是否被填入,以及你是否在编辑后重启了服务器。

"Local environment loading requires Node.js 20.12 or newer." 你的 Node 版本对于项目内置的 .env 加载器来说太旧了。从 nodejs.org 安装当前 LTS 版本 Node 24,然后再次运行 npm start。你不需要 dotenv。

模型未找到错误 通常意味着 AI_MODEL 和 AI_URL 不匹配,例如 OpenAI 模型 ID 对 OpenRouter 的 URL。当你切换提供商时,一起改变所有三个变量。

前端 API 调用返回 404 表明 Express 没有运行或在代理期望的不同端口上。看你的终端:你应该看到 Express 行和 Vite 行。如果只有 Vite 启动,Express 崩溃了,原因会在它上面。

安装完成但 npm start 找不到一个包。 再次运行 npm install,包括请求帮助时的完整输出。下载包括 package-lock.json,所以 pnpm 和工作区配置不涉及。

一切看起来都对,但它仍然失败。 把它带到课程 Discord,告诉他们你运行了什么以及回来了什么。设置问题几乎总是特定于一台机器,通常有人已经遇到过你的问题。

Juno如果某些东西不工作 从确切的错误文本开始,在上面的列表中找到它。端口错误指向被使用的端口,缺少变量和身份验证错误指向 .env,前端 404 通常意味着 Express 没有运行。

在每次改变 .env 后用 npm start 重启。

Juno如果某些东西不工作 把设置当作三个检查点:依赖已安装,两个进程都在运行,所有三个 AI 变量都同意一个提供商和模型。

第一个失败的检查点告诉你要看哪个层,所以在触及它之后的任何东西之前修复那个。

Juno如果某些东西不工作 按边界读取失败:npm 解析包,environment.js 加载凭证,Express 拥有提供商流量,Vite 代理浏览器 API 请求。

验证失败前面的边界,而不是一次改变几个层。