不使用框架的简单Node.js应用应采用怎样的项目结构?
无第三方框架极简API项目结构方案
仅需安装dotenv和你所用数据库对应的驱动包(比如mysql2、pg等),无其他任何重型框架依赖,完全适配你所说的仅支持基础API请求、数据库读写的极简脚本场景。
最终项目结构
your-project/ ├── index.js # 项目入口 ├── config.js # 全局配置 ├── route-handler.js # API路由匹配与请求处理 ├── db/ │ ├── index.js # 数据库连接初始化 │ └── crud.js # 通用数据库增删改查封装 ├── utils/ │ └── request.js # 请求参数解析、响应格式化工具 └── .env # 敏感环境变量
各文件职责说明
index.js:项目启动入口,仅做三件事:加载配置、初始化数据库连接、启动原生http服务监听端口,示例代码:
const http = require('http') const { PORT } = require('./config') const { initDb } = require('./db') const routeHandler = require('./route-handler') initDb().then(() => { http.createServer(routeHandler).listen(PORT, () => console.log(`服务启动在端口${PORT}`)) })
config.js:统一管理所有固定配置,引用.env的敏感变量,避免硬编码散落在各个文件:
require('dotenv').config() module.exports = { PORT: process.env.PORT || 3000, DB_CONFIG: { host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PWD, database: process.env.DB_NAME } }
route-handler.js:所有API路由的匹配逻辑,用原生判断即可不需要引入路由框架:
const { parseReq, sendRes } = require('./utils/request') const { addData, queryData } = require('./db/crud') module.exports = async (req, res) => { const { method, path, body } = await parseReq(req) // 路由匹配,新增接口直接在这里加规则即可 if (method === 'GET' && path === '/api/query') return sendRes(res, 200, await queryData(body.id)) if (method === 'POST' && path === '/api/add') return sendRes(res, 200, await addData(body)) return sendRes(res, 404, { msg: '接口不存在' }) }
db/index.js:仅封装数据库连接、断开逻辑,不要和业务CRUD逻辑混写:
const mysql = require('mysql2/promise') const { DB_CONFIG } = require('../config') let pool async function initDb() { pool = mysql.createPool(DB_CONFIG) await pool.getConnection() console.log('数据库连接成功') } module.exports = { initDb, pool }
db/crud.js:所有和数据库读写相关的业务逻辑都放在这里,上层不需要直接操作数据库连接:
const { pool } = require('./index') async function queryData(id) { const [rows] = await pool.query('SELECT * FROM test_table WHERE id = ?', [id]) return rows[0] } async function addData(data) { const [res] = await pool.query('INSERT INTO test_table SET ?', [data]) return { insertId: res.insertId } } module.exports = { queryData, addData }
utils/request.js:统一处理请求参数解析、响应格式化,避免每个接口重复写header、解析body的代码:
function parseReq(req) { return new Promise(resolve => { let body = '' req.on('data', chunk => body += chunk.toString()) req.on('end', () => resolve({ method: req.method, path: req.url.split('?')[0], body: body ? JSON.parse(body) : {} })) }) } function sendRes(res, code, data) { res.setHeader('Content-Type', 'application/json') res.writeHead(code) res.end(JSON.stringify(data)) } module.exports = { parseReq, sendRes }
.env:存放所有敏感信息,不要提交到代码仓库,示例:
PORT=3000 DB_HOST=127.0.0.1 DB_USER=root DB_PWD=123456 DB_NAME=test_db
后续扩展规则
严格遵循以下规则即可避免后续开发结构混乱:
- 新增接口直接在
route-handler.js加路由匹配规则 - 新增数据库操作直接在
db/crud.js加对应方法 - 新增通用工具函数都放在
utils目录下 - 所有配置都统一放在
config.js和.env
内容的提问来源于stack exchange,提问作者aaron
相关产品推荐
相关产品推荐

