为什么一行 npm install 都不用
2024 年接第一个建站单子时,我在 package.json 面前犹豫了很久。Express?Koa?Fastify?每个框架都有学习成本、版本兼容问题、以及最重要的——客户的维护成本。
最后我关掉了 npm,打开了一个空文件夹。
零依赖不等于原始。 Node.js 内置的 http、fs、crypto、zlib 模块已经覆盖了建站需要的全部能力。你缺的不是框架,是把这些模块组合起来的经验。
真实项目架构
以鲜味居(粤菜餐厅官网)为例,完整技术栈:
前端: 纯 HTML + CSS + JS(零框架)
后端: Node.js 原生 http 模块
数据库: JSON 文件读写
启动: node server.js
整个项目没有 node_modules 目录,克隆下来就能跑。部署到客户的 Windows 服务器上,不需要配环境、不需要解决依赖冲突——双击 bat 脚本就上线。
原生 http 路由表
很多人觉得不用 Express 写路由会很痛苦。实际上,一个简单的路由分发器不超过 20 行:
const routes = [];
function route(method, pattern, handler) {
routes.push({ method, regex: new RegExp('^' + pattern + '$'), handler });
}
async function handleAPI(req, res) {
for (const r of routes) {
if (r.method !== req.method) continue;
const match = req.url.match(r.regex);
if (!match) continue;
await r.handler(req, res);
return true;
}
return false;
}
鲜味居项目有 16 个 API 端点,全部通过这个分发器处理。路由注册用 if-else 链还是用上面的 route 函数,纯粹是组织方式的区别——效果一样。
JSON 数据库的原子写入
很多人担心 JSON 文件作数据库不可靠。解决方法是原子写入:
function writeJSON(filename, data) {
const p = path.join(DATA_DIR, filename);
fs.writeFileSync(p + '.tmp', JSON.stringify(data, null, 2));
fs.renameSync(p + '.tmp', p);
}
先写 .tmp,再 rename。rename 是原子操作——要么成功,要么失败,不存在写一半崩溃导致数据损坏。这是操作系统保证的,不是 Node.js 的特性。
安全:零依赖意味着零供应链攻击
2024-2025 年 npm 供应链攻击频发。left-pad 事件、event-stream 后门、ua-parser-js 挖矿——每次都是成千上万项目受影响。
零依赖架构天然免疫这些。你的攻击面缩小到了 4 个内置模块:http、crypto、fs、zlib。Go 标准库经过 Google 审查,Node.js 核心模块经过社区审查,安全性远超任何第三方 npm 包。
真正的边界在哪
零依赖不是万能药。以下场景不适用:
- 复杂模板渲染:用 EJS/Pug 比手写字符串拼接更高效
- ORM:数据关系复杂时,手写 SQL/JSON 查询容易出错
- WebSocket:原生
ws需要手动处理帧协议,不如直接用ws库
但对于中小实体店官网这个细分市场——零依赖是最优解。
实战建议
如果你也想尝试零依赖全栈:
- 从 server.js 骨架开始:路由分发 + 静态文件 + JSON 读写,200 行就够
- 安全优先:scrypt 密码哈希 + XSS 转义 + 速率限制,一个不能少
- Gzip 压缩:
zlib.gzipSync()一行代码,HTML/CSS/JS 体积减 70% - 原子写入:数据永远用
.tmp+rename模式 - 部署用 Vercel:
api/index.js单文件全路由,零配置上线
完整项目源码在 GitHub 开源,欢迎参考。