1. 从零启动 Nodejs 项目准备工作到底要做哪些Nodejs 项目从零启动真正卡人的往往不是写业务代码而是环境准备这一关npm 装包慢到怀疑人生、环境变量散落在各个文件里、mongoose 连接初始化写错一个参数就报超时。这篇就把这三件事一次讲清楚给出一套可以直接复制的.npmrc、.env与 config 骨架并且用 TaoToken 的统一 Key 完成一次接口连通性验证让你在写第一行业务逻辑之前基础工程已经能跑起来。适合谁看刚接触 Nodejs 后端、准备搭一个 Express mongoose 小服务的人或者手上项目环境配置比较乱、想统一收口的人。全程命令都可以直接粘贴执行Windows 和 macOS 的差异我会单独标出来。我试过把 npm 源、环境变量、数据库连接、模型调用通道分散在四个地方管理后来发现只要在项目初始化阶段统一收口后面维护成本会低很多。下面按「先装工具、再配源、再管变量、最后验证连通」的顺序来。2. TaoToken 前置准备统一 Key 与 API 通道在开始写配置之前先把外部通道准备好。TaoToken 在这里扮演的角色是「统一的模型调用入口」——你不需要在项目里维护多套 Key 和多套 base URL一个 Key 走一个 API 地址后面不管是接对话模型还是接编码类模型改的都是配置而不是代码。官网地址https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentAPI 地址https://taotoken.net/api你需要提前做两件事第一拿到 API Key。进入控制台的 API Keys 页面创建一个新 Key复制出来先存到安全的地方后面写进.env文件。地址https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite第二确认你要调用的模型名。不同模型对应的名称不一样建议先在模型对话页面确认一下可用模型和返回格式避免配置写完了才发现模型名拼错。地址https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite注意Key 只写进.env不要硬编码进config.js更不要提交到 Git。后面我会给.gitignore的写法。如果你后续要做长期编码类任务或者 Agent 类项目可以了解一下 Coding Plan它更适合持续性的调用场景https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite3. 可复制配置.npmrc、.env 与 config 骨架3.1 安装 Nodejs 并验证先去 Nodejs 官网下载安装包Windows 推荐.msi格式因为它默认会把 npm 的环境变量配好省掉手动配 Path 的步骤。安装完成后打开终端验证node -v npm -v两条命令都能打印出版本号说明安装成功。如果提示「不是内部或外部命令」说明环境变量没配好需要手动把 Nodejs 安装目录包含node.exe和npm.cmd的那个目录加到系统 Path 里。3.2 配置 npm 源与淘宝镜像国内直连官方源经常慢换成国内镜像会快很多。推荐用项目级.npmrc而不是全局命令这样配置跟着项目走换机器不用重新设。在项目根目录新建.npmrcregistryhttps://registry.npmmirror.com disturlhttps://npmmirror.com/mirrors/node electron_mirrorhttps://npmmirror.com/mirrors/electron/这里用的是registry.npmmirror.com它是目前维护中的镜像地址。老教程里常见的registry.npm.taobao.org已经停止服务继续用会报证书或 404 错误这是很多人踩过的坑。如果你确实需要全局切换可以用命令npm config set registry https://registry.npmmirror.com npm get registry第二条命令用来确认当前生效的源。想切回官方源就把地址换成https://registry.npmjs.org。3.3 环境变量管理.env 骨架环境变量用dotenv管理最省事。先装依赖npm init -y npm install dotenv mongoose express然后在项目根目录建.env# 服务端口 PORT3000 # 数据库连接 MONGO_URImongodb://127.0.0.1:27017/demo # TaoToken 统一通道 TAOTOKEN_API_KEYsk-你的Key TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_MODEL你的模型名配套的.gitignore一定要加上node_modules/ .env *.log3.4 config 骨架把散落的配置收口新建config/index.js把环境变量读进来并做一次校验避免运行时才发现某个变量是 undefinedrequire(dotenv).config(); const required [MONGO_URI, TAOTOKEN_API_KEY, TAOTOKEN_BASE_URL]; for (const key of required) { if (!process.env[key]) { throw new Error(缺少环境变量: ${key}请检查 .env 文件); } } module.exports { port: Number(process.env.PORT) || 3000, mongo: { uri: process.env.MONGO_URI, options: { serverSelectionTimeoutMS: 5000, maxPoolSize: 10, }, }, taotoken: { apiKey: process.env.TAOTOKEN_API_KEY, baseUrl: process.env.TAOTOKEN_BASE_URL, model: process.env.TAOTOKEN_MODEL, }, };这样做的价值在于业务代码里只require(../config)不再到处process.env.XXX。哪天要换 Key 或者换地址只改一处。3.5 mongoose 连接初始化新建db/mongo.js把连接逻辑单独抽出来并加上重连和错误日志const mongoose require(mongoose); const config require(../config); async function connectMongo() { mongoose.connection.on(connected, () { console.log([mongo] 连接成功); }); mongoose.connection.on(error, (err) { console.error([mongo] 连接错误:, err.message); }); mongoose.connection.on(disconnected, () { console.warn([mongo] 连接断开尝试重连); }); await mongoose.connect(config.mongo.uri, config.mongo.options); return mongoose.connection; } module.exports { connectMongo };入口文件app.js里这样调用const express require(express); const config require(./config); const { connectMongo } require(./db/mongo); const app express(); app.use(express.json()); app.get(/health, (req, res) { res.json({ ok: true, ts: Date.now() }); }); (async () { await connectMongo(); app.listen(config.port, () { console.log(服务已启动: http://127.0.0.1:${config.port}); }); })();4. 验证请求用统一 Key 跑一次连通性测试配置写完必须验证否则等于没配。这里分两步先验证本地服务再验证 TaoToken 通道。4.1 验证本地服务与 mongoose启动服务node app.js看到[mongo] 连接成功和服务已启动两行日志说明 mongoose 初始化没问题。再开一个终端请求健康检查接口curl http://127.0.0.1:3000/health返回{ok:true,ts:...}就通过了。4.2 验证 TaoToken 通道新建scripts/check-taotoken.js用 Nodejs 内置的 fetch 发一次请求Node 18 自带const config require(../config); async function check() { const res await fetch(${config.taotoken.baseUrl}/v1/chat/completions, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer ${config.taotoken.apiKey}, }, body: JSON.stringify({ model: config.taotoken.model, messages: [{ role: user, content: 只回复两个字连通 }], }), }); if (!res.ok) { const text await res.text(); throw new Error(请求失败 ${res.status}: ${text}); } const data await res.json(); console.log(通道正常返回:, data.choices?.[0]?.message?.content); } check().catch((err) { console.error(验证失败:, err.message); process.exit(1); });执行node scripts/check-taotoken.js终端打印出模型返回内容说明 Key、base URL、模型名三者都对上了。这一步跑通之后你后面接任何业务逻辑都只是替换 messages 的事。提示如果返回 401优先检查 Key 是否复制完整、有没有多余空格返回 404 一般是 base URL 或路径拼错返回模型不存在去模型对话页面核对模型名。5. 本篇常见错误排查5.1 npm 装包报证书错误或 404大概率是还在用registry.npm.taobao.org。这个域名已经停服换成https://registry.npmmirror.com即可。检查当前源npm config get registry如果输出还是老地址删掉项目里的.npmrc重新写或者执行npm config delete registry清掉全局残留。5.2 mongoose 连接超时报Server selection timed out通常是三个原因本地 MongoDB 服务没启动、连接串里的端口写错、或者serverSelectionTimeoutMS设得太短。先在终端确认 MongoDB 在跑再核对MONGO_URI里的库名和端口。云数据库还要检查 IP 白名单。5.3 环境变量读不到process.env.XXX是 undefined常见原因是.env文件和执行命令的目录不在同一层。dotenv默认从当前工作目录找.env所以要在项目根目录执行node app.js。如果入口文件在子目录需要显式指定路径require(dotenv).config({ path: require(path).resolve(__dirname, ../.env) });5.4 端口被占用报EADDRINUSE说明 3000 端口被别的进程占了。改.env里的PORT或者查一下占用进程# macOS / Linux lsof -i :3000 # Windows netstat -ano | findstr :30005.5 请求 TaoToken 返回 401 或 403先确认请求头里Authorization是Bearer加 Key中间有一个空格。再确认 Key 没有过期或被删除。如果 Key 是在别的环境生成的注意不要带上前后的引号一起复制进.env。6. 把通道固定下来后面就省心了环境准备这件事做一次做对后面每个新项目都能复用同一套骨架.npmrc管源.env管变量config/index.js管收口db/mongo.js管连接scripts/check-taotoken.js管通道验证。五个文件加起来不到一百行但能省掉大量「为什么本地能跑线上不行」的排查时间。如果你后面要接更多模型或者做持续性的编码任务建议把 Key 的管理也统一到控制台里需要新建或轮换 Key 时直接去 API Keys 页面操作https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite接入过程中遇到参数或路径问题可以对照接入文档核对请求格式https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite先把node scripts/check-taotoken.js跑通再去写你的第一个路由顺序别反。