node.js开发
node.js开发
最近, 学院打算部署一个DeepSeek
用于2025级招生问答工作, 苏喵觉得学院方案并不可行, 所以, 我编写了一个基于DeepSeek API
和本地数据库的程序Kirafint
.
该程序使用nodejs
编写, 过程中咱也学到了很多东西, 这里一一分享一下.
1. node文件结构
一个node
程序结构如下:
<Project Name>
├── node_modules/
├── src
│ ├── index.js
│ ├── cli
│ │ └── cli.js
│ └── other
│ ├── file1.js
│ └── file2.json
├── .gitignore
├── package.json
├── package-lock.json
├── pnpm-lock.yaml
└── README.md
上述file-tree
中, 有些文件由包管理器
直接生成, 其他文件为自己编写, 下面一一讲解.
1.1 必须文件
1.1.1 src/
文件夹
src/
文件夹是整个项目的程序文件, 该文件夹所有完全由开发者编写.
src/index.js
是整个程序都入口文件
, 运行该模块时, 实际上就行以运行该文件的方式运行.
src/
文件夹其他文件多以文件夹包裹, 为其他逻辑, 接口等功能文件.
src/
文件夹中也有一些约定俗成的文件(夹), 如src/utils/
文件夹, 用于存储插件(如自己编写的日志工具)等.
1.1.2 package.json
文件
package.json
是项目的清单, 是整个工具的配置中心.
专业详细的讲解详见node官方文档 入门教程/package.json指南
package.json
文件如下内容如下:
{
"name": "project_name",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {},
"keywords": [],
"author": "",
"license": "MIT",
"packageManager": "[email protected]",
"dependencies": {}
}
其中:
name
,version
,description
: 项目名, 版本号, 描述main
: 程序主入口scripts
: 定义了一组可以运行的脚本license
: (开源)协议packageManager
: 包管理器, 示例使用的是pnpm
dependencies
: 项目依赖, 当项目使用某外部库时, 需要在此处写明(一般IDE会自动添加), 之后包管理器会自动下载相应包.
当我们使用包管理器初始化一个node项目时, package.json
文件会自动生成.
1.2 包文件
1.2.1 package-lock.json
文件
package.json
文件中, 对依赖的版本并不明确. 例如对于某依赖的0.13.0
版本, 若写入~0.13.0
, 则意味着0.13.*
版本均可用; 若写入^0.13.0
, 则意味着0.13.0+
(包括0.14.*
等更高版本)均可用; 只有写入0.13.0
时, 才会固定0.13.0
版本.
当文件发送给他人, 使用pnpm install
时, 包管理器会下载许可的最新依赖. 也就是除了写死0.13.0
版本外, 会自动下载~0.13.0
中的0.13.<max>
和^0.13.0
的最新版本.
所以使用package-lock.json
文件, 固定了现在包的版本. 当使用pnpm install
安装/更新时, 该文件不会变化; 只有明确使用pnpm install
更新时, 该文件才会发生变化.
1.2.2 pnpm-lock.yaml
文件
别问, 窝也不知道...
1.2.3 node_modules/
文件夹

如图所示.
node_mudules
文件夹是自动生成的依赖文件夹. 但是前端社区经常各种互相依赖, 所以可能所需几个依赖, 但最终下载了一大堆东西.
不过该文件夹并不需要开发者管理, 包管理器会自动填满它.
1.3 自定义文件
README.md
没啥可说的.
.gitignore
一定要写上node_modules/
!!
2. 常用库
不定期更新
2.1 commander
commander
库是用于命令行程序入口的库, 在index.js
中引用commander
, 可快速制作一个cli入口.
const {Command} = require("commander");
const program = new Command();
之后可以如下定义程序的name
, description
和其他操作.
Kirafint
的定义如下所示:
program
.name("Kirafint")
.description("基于Deepseek API和本地模型的AI Demo")
.option("-c, --cli", "命令行模式")
.option("-s, --server", "服务器模式")
program.parse(process.argv);
定义好name
, description
后, 直接运行该文件, commander
会自动生成入口说明. 例如提示词和使用方法等.
此外, .option()
中规定的参数操作, commander
也就自动根据提示生成-h, --help
帮助提示.
直接运行该文件效果如下:
Usage: Kirafint [options]
基于Deepseek API和本地模型的AI Demo
Options:
-c, --cli 命令行模式
-s, --server 服务器模式
-h, --help display help for command
在.option()
中规定的参数(flag
)会被处理成对象的属性, 可用如下代码检测读取到的参数:
const options = program.opts();
if (options.cli) {
// cli 部分代码
} else if (options.server) {
// server 部分代码
} else if (Object.keys(options).length === 0) {
program.help();
}
当输入node src/index -c
时, options.cli
为true
, 执行对应代码.
此外, .option()
中还可以自定义参数, 例如:
program.option("-f, --float <number>", "float argument", parseFloat);
这样会对opts
新建一个float
属性, 类型为float
(因为结尾的parsefloat
).
我们可以使用如下代码检查用户是否输入该命令或输入了什么参数:
const options = program.opts();
if (options.float !== undefined) {
// 我是代码
}
代码和示例摘自Commander中文网开发文档/选项/自定义选项处理
2.2 chalk
chalk
提供了一系列终端字符串样式, 可以轻松的调整输出的颜色, 字体等.
该库使用十分简单, 直接展示代码:
const chalk = require("chalk");
console.log(chalk.blue("Hello world!"))
console.log(chalk.blue.bgRed.bold("Hello chalk~"));
console.log(chalk.blud("Hello", "World!", "Foo"));
console.log(chalk.red("Hello", chalk.underline.bgBlue("World") + "!"));
console.log(chalk.rgb(123, 45, 67).underline("Underlined reddish color"));
console.log(chalk.hex('#DEADED').bold('Bold gray!'));
上述代码差不多覆盖了chalk
的所有应用场景.
Chalk中文网开发文档