共计 2669 个字符,预计需要花费 7 分钟才能阅读完成。
技术选型对比
对于新手来说,选择合适的全栈技术组合是第一步。目前主流的全栈组合有 MEAN、MERN 和 JAMstack,它们各有特点:

- MEAN (MongoDB + Express + Angular + Node.js):适合企业级应用,Angular 的学习曲线较陡峭
- MERN (MongoDB + Express + React + Node.js):当前最流行的组合,React 相对容易上手
- JAMstack (JavaScript + APIs + Markup):适合内容型网站,强调静态生成和 CDN 分发
建议新手从 MERN 开始,因为 React 的组件化思维和丰富的生态系统能让开发更高效。
环境搭建
使用 Vite+Express 可以快速初始化项目:
-
创建前端项目:
npm create vite@latest frontend --template react cd frontend npm install axios react-router-dom -
创建后端项目:
mkdir backend cd backend npm init -y npm install express mongoose bcrypt jsonwebtoken redis cors dotenv
关键 package.json 依赖说明:
- 前端:axios 用于 HTTP 请求,react-router-dom 处理路由
- 后端:mongoose 操作 MongoDB,bcrypt 处理密码哈希,jsonwebtoken 生成 JWT
核心实现 – 用户认证模块
前端实现
使用 React Hook 表单验证:
// LoginForm.jsx
import {useForm} from 'react-hook-form';
export default function LoginForm() {const { register, handleSubmit} = useForm();
const onSubmit = async (data) => {const res = await axios.post('/api/auth/login', data);
localStorage.setItem('token', res.data.token);
};
return (<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('email')} type="email" />
<input {...register('password')} type="password" />
<button type="submit"> 登录 </button>
</form>
);
}
后端实现
Node.js 中使用 bcrypt 和 JWT:
// authController.js
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
const login = async (req, res) => {const user = await User.findOne({ email: req.body.email});
if (!user) return res.status(404).send('用户不存在');
const validPassword = await bcrypt.compare(req.body.password, user.password);
if (!validPassword) return res.status(400).send('密码错误');
const token = jwt.sign({_id: user._id}, process.env.JWT_SECRET);
res.header('Authorization', token).send({token});
};
数据库设计
Mongoose Schema 最佳实践:
// userModel.js
import mongoose from 'mongoose';
const userSchema = new mongoose.Schema({email: { type: String, required: true, unique: true},
password: {type: String, required: true},
createdAt: {type: Date, default: Date.now}
});
userSchema.pre('save', async function(next) {if (!this.isModified('password')) return next();
this.password = await bcrypt.hash(this.password, 10);
next();});
export default mongoose.model('User', userSchema);
避坑指南
新手容易忽略的三个安全问题:
- CSRF 防护缺失:使用 csurf 中间件或 SameSite Cookie 属性
- 明文密码存储:始终使用 bcrypt 等库进行哈希
- JWT 无过期时间:设置合理的 expiresIn 选项
部署实战
使用 Docker Compose 编排服务:
# docker-compose.yml
version: '3'
services:
frontend:
build: ./frontend
ports:
- "3000:3000"
backend:
build: ./backend
ports:
- "5000:5000"
environment:
- MONGO_URI=mongodb://mongo:27017/app
mongo:
image: mongo
volumes:
- mongo-data:/data/db
volumes:
mongo-data:
Nginx 反向代理配置:
server {
listen 80;
location / {proxy_pass http://frontend:3000;}
location /api {proxy_pass http://backend:5000;}
}
总结与思考
通过这个完整的 MERN 项目实践,你应该已经掌握了全栈开发的基本流程。在实际项目中,还有许多需要深入思考的问题:
- 什么时候应该选择 GraphQL 替代 REST API?
- 如何优化前端性能,比如代码分割和懒加载?
- 后端如何实现分页和缓存策略?
全栈开发是一个不断学习的过程,建议从这个小项目开始,逐步扩展功能,比如添加用户权限管理、文件上传等功能。完整的代码示例可以在 GitHub 仓库 中找到。
最后,记住全栈工程师的核心价值不在于掌握多少技术,而在于能够用合适的技术解决实际问题。保持好奇心,持续学习,你会在全栈开发的道路上走得更远。
正文完
