Node.js新手教程:从零开始学习服务器端JavaScript
从一个静态页面开始,我如何走上Node.js之路?

大家好,我是林工,现在在一家电商公司负责前端开发。说起来可能有些惭愧,刚入职的时候我还是个只会写HTML/CSS/JS的“纯前端”,服务器那边的事儿基本没碰过。但随着时间推移,项目需求越来越复杂,尤其是我们接手了一个老系统重构的工作,让我不得不跨出舒适区,开始接触 Node.js。
今天这篇文章,我想和大家分享一下我当时是怎么从零开始学 Node.js 的,过程中踩了哪些坑,也希望能给正在学习或者打算入门 Node.js 的同学一些实用的经验。毕竟,作为一个走过了弯路的人,我觉得有些事早点知道,真的能少走很多冤枉路。
初识 Node.js:为什么我要学它?
记得当时我们要做一个商品详情页的优化项目,其中有一个功能是“商品浏览记录”——也就是用户访问过的商品会显示在侧边栏里,方便回看。
这个功能看起来很简单,但如果要实现持久化存储(比如刷新页面还能保留),就得通过后端保存数据。那时候我们团队的后端是 Java 组,接口对接需要排队、联调,效率很低。再加上当时的前端工程架构已经用上了 Webpack 和 Vue,整个流程都在 JS 体系下完成,我突然想到:“如果我能自己搞一个本地的服务把数据存起来,是不是可以先把功能跑通,再对接正式接口?”
于是,Node.js 就走进了我的视野。说白了,就是想找个 JS 写服务端的办法,不折腾别的语言。
第一次实践:搭建一个本地服务器
刚开始查资料的时候,网上一堆“Hello World”级别的示例,但真正上手才发现——这些例子离“生产级应用”差得远了。于是我决定先从基础做起:搭一个最简单的 HTTP 服务器,用来模拟后端返回商品信息。
// server.js
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ name: 'T恤', price: 99 }));
});
server.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
这段代码其实就用了 Node.js 原生的 http 模块,启动一个服务器,监听 3000 端口。浏览器访问这个地址就能拿到 JSON 数据了。
虽然很简单,但对我来说是个不小的突破。从此我知道,原来不用 PHP 或 Java,也可以写出响应请求的服务。
遇到的第一个挑战:路由管理太麻烦
不过问题很快来了:随着接口变多,我每次都要手动判断路径,比如 /product/list, /user/info 这些,每个都去 if-else 分发,代码很快就变得难以维护。
这时候我意识到一个问题——原生的 http 模块太底层了,不适合真实项目开发。那怎么办呢?社区推荐了很多框架,Express 是最流行的。所以我决定换 Express 来重构我的小项目。
npm install express
然后新建 app.js 文件:
const express = require('express');
const app = express();
app.get('/product/list', (req, res) => {
res.json([
{ id: 1, name: 'T恤', price: 99 },
{ id: 2, name: '牛仔裤', price: 149 },
]);
});
app.get('/user/info', (req, res) => {
res.json({ name: '林工', level: '高级前端' });
});
app.listen(3000, () => {
console.log('Server running at http://localhost:3000');
});
这下好了,路由清晰多了,也能按模块拆分逻辑。后来我还用 express.Router() 把不同功能拆分成子路由,结构更清晰。
更大的挑战:连接数据库,实现持久化
前面的例子都是模拟数据,但真正的业务场景中,肯定需要用到数据库。比如刚才提到的商品浏览记录功能,就需要将用户的访问记录存进数据库,而不是存在内存里。
我们选的是 MongoDB,因为它也是基于 JS 的,和 Node.js 结合起来比较自然。引入 Mongoose 库来操作数据库:
npm install mongoose
然后初始化数据库连接:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/shop', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
console.log('Connected to MongoDB');
});
接着定义一个浏览记录模型:
const visitedSchema = new mongoose.Schema({
productId: Number,
timestamp: { type: Date, default: Date.now },
});
const Visited = mongoose.model('Visited', visitedSchema);
最后,在接口中处理数据:
app.post('/record/add', async (req, res) => {
const newRecord = new Visited({ productId: req.body.productId });
await newRecord.save();
res.json({ success: true });
});
这样就能实现实时的用户行为记录了!
踩坑经验分享
1. Node.js 异步回调带来的混乱
一开始写接口的时候,我经常被异步回调搞得晕头转向。比如数据库插入之后要返回结果,但我写成了下面这样:
Visited.create({ productId }, function (err, doc) {
// do something...
});
res.json({ success: true }); // 这行会先执行!
因为 Node.js 是异步非阻塞的,所以这种写法会导致还没插入完成就返回了结果。正确的做法应该是放在回调里面,或者用 async/await:
app.post('/record/add', async (req, res) => {
const newRecord = new Visited({ productId: req.body.productId });
await newRecord.save();
res.json({ success: true });
});
2. 忘记加 CORS 中间件导致跨域失败
我们在前端是用 Vue + Axios 请求的,但 Node 服务在 localhost:3000,Vue 项目在 localhost:8080,这就导致了跨域问题。
解决方法是装一个中间件:
npm install cors
然后在入口文件加上:
const cors = require('cors');
app.use(cors());
一下子搞定,非常方便。
3. NODE_ENV 没设置清楚,开发环境暴露敏感信息
有一次我把数据库连接配置写死了,还在开发环境下输出错误堆栈信息,结果测试人员不小心访问到了报错页面,直接看到了数据库账号密码……吓坏了 QA。
后来我改成了:
if (process.env.NODE_ENV !== 'production') {
app.use(express.json());
}
同时把数据库配置抽出来,统一用 .env 管理。
实际效果与收获
这套本地服务后来成为了我们内部工具的一部分,甚至后续还上线了一个小型的数据统计平台。更重要的是,它让我真正理解了前后端协作的本质。过去我一直觉得后端是黑盒子,但现在我明白了他们的工作原理,沟通也顺畅多了。
而且,有了 Node.js 的基础之后,我也能更好地参与构建工具链、脚本自动化等工作,比如写一个自动清理 CDN 缓存的脚本,或者搭建本地 Mock 服务,大大提高了开发效率。
我的一些建议
别一开始就学太多框架
很多新手看到 Express、Koa、NestJS 等各种框架,容易选择困难。我的建议是先掌握 Express,它是社区最成熟、文档最多的一个。打好基础后再去尝试其他框架。
注重模块化设计,别写面条代码
后期如果你要做中大型项目,模块化是必须的。把路由、控制器、服务、模型分离,用 Router 拆分功能模块,才能维护得下去。
尽早接入调试工具,比如 nodemon 和 VS Code Debugger
开发过程中频繁重启服务很烦人,安装
nodemon监听变化自动重启,提升效率;VS Code 的 Debugger 功能也非常强大,断点调试比 console.log() 高级得多。注意安全性
早期我完全没考虑安全问题,后来才明白输入验证的重要性,比如防止 SQL 注入(虽然 Node 多数是 NoSQL,但也要防注入)、限制 API 调用频率等。可以用像 Joi 或者 celebrate 这样的库做参数校验。

拥抱 TypeScript
如果你打算长期使用 Node.js,建议尽快迁移到 TypeScript。TS 能减少很多类型错误,也能提高团队协作的可维护性。
多关注性能与稳定性
比如 Node.js 默认是单线程的,可以考虑配合 Cluster 模块或多进程部署来利用多核 CPU;也可以用 PM2 做进程管理和热更新,避免服务中断。
写在最后
学习 Node.js 并不是为了变成全栈工程师,而是为了让我们作为前端开发者,有更多的可能性和掌控力。在这个前后端融合的时代,了解服务端逻辑,不仅能提升你的开发能力,更能帮助你在团队中更有话语权。
希望这篇结合我个人经历的文章,对你们有用。如果你也有类似的故事或者踩过类似的坑,欢迎留言交流,我们一起成长。

评论 0