- 包管理器:开发与 CI 使用
pnpm,Dockerfile也用 pnpm(pnpm@9 --frozen-lockfile,匹配pnpm-lock.yaml)。仓库没有yarn.lock,不要引入 yarn。 - Node 版本:README 推荐 Node 22+;
package.json的engines声明>=12;CI/打包在 Node 18–24 上运行。现代 Node 均可。 - 环境变量:
server.js调用了dotenv.config(),本地.env会被自动加载;所有支持的变量见.env.prod.example。
- 安装依赖:
pnpm i - 启动服务:
pnpm start(等价node app.js);热重载开发:pnpm dev(nodemon) - 跑测试:
pnpm test(Mocha,超时 60s) - Lint:
pnpm lint;自动修复:pnpm lint-fix - 文档格式化检查/修复:
pnpm docs:check/pnpm docs:format - 打包独立二进制:
pnpm pkgwin/pkglinux/pkgmacos
app.js(也是bin)——服务入口。先确保os.tmpdir()里存在anonymous_token,执行generateConfig()刷新匿名 cookie 与 xeapi 公钥,再调用server.serveNcmApi()。server.js——Express 工厂。constructServer()自动扫描module/*.js,每个文件注册一条路由(文件名_转/,如album_new.js→/album/new;特例daily_signin/fm_trash/personal_fm硬编码在server.js的special对象里)。serveNcmApi()监听PORT(默认 3000)/HOST。main.js——作为依赖被引入时的入口(main字段)。把每个module/*导出为同名函数name(data),另导出server、serveNcmApi、getModulesDefinitions。module/*.js——每个接口一个文件,标准写法:module.exports = (query, request) => request(path, data, createOption(query))。createOption在util/option.js,负责 crypto、cookie(回退到NETEASE_COOKIE)、proxy、realIP/randomCNIP、headers、timeout。util/request.js——唯一的对外 HTTP 层(axios)。按crypto(api/eapi/weapi/linuxapi/xeapi)加密并设置 IP 头;在 require 时同步读取os.tmpdir()里的anonymous_token与xeapi_public_key。util/config.json——运行时配置:网易域名 +APP_CONF.encrypt: true(默认走 eapi 加密)。已被 git 跟踪,改动会改变全局默认行为。index.js/index.mjs——require('./app.js')的薄包装,供 Vercel(vercel.json)和 ESM 导入使用。
- 新建
module/xxx.js会自动挂载路由,无需注册;文件名即路由。 - 照抄同目录模块的写法(选对
crypto),用createOption(query)生成请求选项。 - 改文件名/路由会破坏已有客户端,尽量保持旧路径兼容。
pnpm test跑server.test.js+main.test.js。server.test.js在before()里启动真实服务器,test/*.test.js全部请求真实网易云 API——必须联网,且可能因上游风控/限流偶发失败。main.test.js是纯单测。- 测试使用
power-assert(经intelli-espower-loader),普通assert写法也会输出详细 diff。 - 只跑单个用例:
pnpm exec mocha -r intelli-espower-loader -t 60000 --grep "<describe/it 名字>" server.test.js main.test.js --exit
- 改
package.json的version会触发自动发布:push 到main后会自动打 GitHub Release(pkg二进制)、构建并推送 Docker 镜像(Docker Hub + GHCR)、pnpm publish到 npm。别顺手改版本号。 - 没有实际 git hooks:
package.json里配了lint-staged,但.husky/下没有真正的 hook,commit 时不会自动跑任何检查,自己记得pnpm lint-fix。 - 代理环境变量已失效:README 里关于
http_proxy/https_proxy的警告来自旧request库时代;现在util/request.js用 axios + 自定义 keep-alive agent,且显式proxy: false,环境变量代理不会生效。按请求走query.proxy参数(支持 PAC 和 http 隧道)。 - 启动令牌在系统临时目录:
anonymous_token、xeapi_public_key存放在os.tmpdir(),util/request.js在 require 时同步读取。文件过期或被清空就重启服务(或调用generateConfig());首次启动先写空文件再刷新。 - ESLint 9 flat config:
eslint.config.js,风格由eslint-plugin-prettier强制(2 空格缩进、单引号、分号、endOfLine: auto)。