MERN 全栈项目搭建
· 阅读需 16 分钟
技术选型
- 前端框架:React
- 后端框架:Express.js + Node.js
- 数据库:MongoDB
预期的项目结构
my-mern-project/ # 项目根目录
│
├── backend/ # 后端代码目录
│ ├── models/ # 数据模型目录
│ ├── routes/ # 路由目录(将 controllers 和 routes 合并到同一个目录,便与后续维护)
│ │ ├── userRoutes.js
│ │ └── userController.js
│ ├── config/ # 配置文件目录
│ ├── index.js # 后端入口文件
│ └── package.json # 后端依赖管理文 件
│
├── frontend/ # 前端代码目录
│ ├── public/ # 静态资源目录
│ ├── src/ # 源代码目录
│ │ ├── components/ # React 组件目录
│ │ ├── pages/ # 页面组件目录
│ │ ├── App.js # React 应用入口文件
│ │ └── index.js # React 应用渲染入口文件
│ └── package.json # 前端依赖 管理文件
│
└── README.md # 项目说明文档
项目搭建步骤
- 新建文件夹 my-mern-project 保存前后端项目
- 新建前后端项目根目录 /frontend, /backend
- 在 frontend、backend 中各自用脚手架初始化项目
- 分别优化前后端项目目录结构
- 基于优化的项目结构启动项目并联调协作
# 新建项目文件夹
mkdirmkdir my-mern-project
cd my-mern-project
# 脚手架初始化前端项目,会创建名为 frontend 的 react 项目
npx create-react-app@latest frontend
# 全局安装 express-generator
npm install -g express-generator
# 脚手架初始化后端项目,会创建名为 backend 的后端项目
express backend --no-view
至此项目结构已经基本搭建起来了,接下来是按照预期的项目结构来优化一下目录结构
后端项目结构优化
└─── backend/ # 后端代码目录
├── models/ # 数据模型目录
├── routes/ # 路由目录(将 controllers 和 routes 合并到同一个目录,便与后续维护)
├── config/ # 配置文件目录
├── index.js # 后端入口文件
└── package.json # 后端依赖管理文件
routes/index.js 统一管理路由,让路由配置更为集中和清晰
routes/index.js
// routes/index.js
const express = require('express')
const router = express.Router()
const userRoutes = require('./userRoutes')
const postRoutes = require('./postRoutes')
router.use('/users', userRoutes)
router.use('/posts', postRoutes)
module.exports = router
routes/userRoutes.js
// userRoutes.js
const express = require('express')
const router = express.Router()
const { getUser, createUser } = require('./userController')
// GET 请求处理
router.get('/', getUser)
// POST 请求处理
router.post('/', createUser)
// 导出路由对象
module.exports = router
routes/userController.js
// userController.js
// 中间件函数 - 获取用户
const getUser = (req, res) => {
// 中间件处理逻辑
res.send('GET request to the homepage')
}
// 中间件函数 - 创建用户
const createUser = (req, res) => {
// 中间件处理逻辑
res.send('POST request to the homepage')
}
// 使用ES6解构导出中间件函数
module.exports = {
getUser,
createUser,
}
提示
postRoutes.js postController.js 的初始化文件结构也基本一致,只是修改一下变量名称
数据库与环境变量配置
安装 dotenv 创建 .env 文件配置全局环境变量
# .env
DB_HOST=localhost
DB_PORT=27017
DB_NAME=mydatabase
DB_USER=myusername
DB_PASS=mypassword
config/env.js 中引入环境变量,配置各个环境的启动参数
// config/env.js
require('dotenv').config()
module.exports = {
development: {
PORT: process.env.PORT || 3000,
MONGO_URI: `mongodb://${process.env.DB_USER}:${process.env.DB_PASS}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`,
// 其他开发环境配置...
},
test: {
PORT: process.env.PORT || 4000,
MONGO_URI: `mongodb://${process.env.DB_USER}:${process.env.DB_PASS}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_NAME}`,
// 其他测试环境配置...
},
production: {
PORT: process.env.PORT || 5000,
MONGO_URI: process.env.MONGODB_URI,
// 其他生产环境配置...
},
}
提示
注意:这里测试环境和开发环境的本地环境配置脚本和上面的 .env 一致
生产环境的话只需要配置 MONGODB_URI=xxxxxx 这一项就可以了
随后在 config/database.js 中引入环境变量,根据不同环境自动读取环境变量
// config/database.js
const envConfig = require('./env')
// 获取当前环境
const ENV = process.env.NODE_ENV || 'development'
// 根据当前环境加载对应的数据库配置信息
const config = envConfig[ENV]
module.exports = config
接下来在 utils/database.js 中创建数据库的连接函数
// utils/database.js
const mongoose = require('mongoose')
const connectDB = async (mongoURI) => {
try {
await mongoose.connect(mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
console.log('MongoDB connected successfully')
} catch (error) {
console.error('Error connecting to MongoDB:', error.message)
process.exit(1) // Exit process with failure
}
}
module.exports = connectDB
最终在入口文件 app.js 中引入配置信息
var express = require('express')
var path = require('path')
var cookieParser = require('cookie-parser')
var logger = require('morgan')
const routes = require('./routes')
// 引入数据库配置
const config = require('./config/database')
// 引入数据库连接函数
const connectDB = require('./utils/database')
var app = express()
app.use(logger('dev'))
app.use(express.json())
app.use(express.urlencoded({ extended: false }))
app.use(cookieParser())
app.use(express.static(path.join(__dirname, 'public')))
// 连接数据库
connectDB(config.MONGO_URI)
// 所有以 /api 开头的请求都会交给 routes 对象处理
app.use('/api', routes)
module.exports = app
mongodb 注册、安装与配置
创建数据库,配置数据库密钥信息,更新不同环境中的环境变量
注册账号,并登录账号
MongoDB: The Developer Data Platform | MongoDB 注册链接
登录完毕之后会看到这样一个界面
登陆完毕先创建一个项目
创建一个免费的云端服务器(512M)
服务器创建完毕之后,创建一个数据库登录账户
设置 IP 访问白名单(选填)
提示
用户账户创建完毕之后,接下来安装图形化界面客户端来连接云服务器
下载 mongodb 客户端
提示
可以直接点击连接安装
提示
也可以在 databse 中点击连接,有支持直接安装的连接
下载完毕之后安装客户端
获取链接并且连接到云服务器
提示
连接成功则表示现在设置的这个链接是确实可以连接到云服务器的,下一步我们要开始创建后端程序,更多的还是通过 API 来操作数据 库
生产环境与开发环境
# e.g. mongodb+srv://admin:kkkkkkkkkk@yyyyyyyy.hhhhhh.mongodb.net/
# 对应的 .env 文件的配置如下
# DB_HOST=yyyyyyyy.hhhhhh.mongodb.net
# DB_PORT=27017
# DB_NAME=<改成你自己创建的数据库名字>
# DB_USER=admin
# DB_PASS=kkkkkkkkkk
如果是本地开发的话,直接启动 dev 模式,然后用 compass 连接本地的数据库就可以实时看到最新的数据库数据总览了
后端项目中初始化数据库配置
首先进入项目根目录,访问 ./backend/package.json 文件,确定项目是否已经安装了 mongoose
依赖
// package.json
{
"name": "backend",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"dotenv": "^16.4.5",
"express": "~4.16.1",
"mongoose": "^8.3.4",
"morgan": "~1.9.1"
}
}
提示
如果没有个 mongoose 这个依赖需要手动安装一下
npm install mongoose
# 或者
yarn add mongoose
backend 目录下创建 models 文件夹
- 创建 index.js 文件,再此处统一引入所有的 model
- 同级目录下创建各个功能模块的 xxxModel.js,后续使用的时候只需要引入 models 这个文件然后做解构就可以了(这个文件夹中主要 是对各个功能的表做定义)
- 接着,在 routes/xxxController.js 文件中对各个模块的功能做封装,对应的 xxxRoute.js 中调用 controller 中的方法
models 中文 件
// models/index.js
const UserModel = require('./userModel')
const PostModel = require('./postModel')
// 引入其他模块的模型...
module.exports = {
UserModel,
PostModel,
// 导出其他模块的模型...
}