全栈设置(Node.js、React.js 和 MongoDB)
每当我需要创建一个新项目时,我都倾向于只使用一种语言。所以我喜欢用 JavaScript 来做所有事情,包括 Node.js、Express.js、React.js,而且我特别喜欢使用像 MongoDB 这样的 NoSQL 数据库。
因此我决定分享我从头开始建立这个环境的经验。
首先,让我们创建一个文件夹并为该项目生成 package.json 文件。
$ mkdir node-react-starter
$ cd node-react-starter
$ npm init -y
现在,让我们安装项目依赖项
$ npm install --save express body-parser mongoose
在这个项目中,我们使用Express.js,这是一个非常流行的 Node.js 应用程序框架。body
-parser用于在处理程序之前的中间件中解析传入的请求主体,该中间件位于 req.body 属性下。Mongoose是一个
MongoDB对象建模工具,旨在在异步环境中工作。
然后,安装开发依赖项
$ npm install --save-dev nodemon concurrently
nodemon是一个运行 node.js 应用程序并监听任何文件更改并更新整个应用程序的包。
并发允许我们同时运行多个 npm 命令。
安装依赖项后,您应该得到如下文件:
让我们创建项目结构
$ mkdir models routes
$ touch index.js
打开index.js文件并添加以下代码:
// index.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const app = express();
mongoose.Promise = global.Promise;
mongoose.connect(process.env.MONGODB_URI || `mongodb://localhost:27017/node-react-starter`);
app.use(bodyParser.json());
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`app running on port ${PORT}`)
});
此后,您可以在 package.json 文件的脚本下添加一个运行脚本:
"server": "nodemon index.js"
此时,您可以运行后端并成功连接到 mongodb(MongoDB 必须已启动并运行)。您可以像这样运行刚刚创建的脚本:
$ npm run server
让我们启动版本控制来跟踪每个更改。但首先我们需要在项目根目录中添加一个 .gitignore 文件,其内容如下:
node_modules
.idea
然后我们启动版本控制
$ git init
$ git add .
$ git commit -am "first commit"
我们成功创建了后端结构,现在让我们跳转到前端。
现在,让我们使用create-react-app创建一个 React 应用程序。
$ create-react-app client
现在,我们必须在客户端目录中添加依赖项。
这里我们将使用yarn来添加这些依赖项。
$ cd client
$ yarn add axios
axios是一个非常流行的基于承诺的浏览器和 node.js HTTP 客户端。
对于 react-scripts >= 0.2.3
对于当前的 react 版本(以及任何其他 react-scripts > 0.2.3),您只需将以下行添加到客户端目录中的package.json 文件中,这将允许您将前端请求代理到后端应用程序。
"proxy": "http://localhost:5000"
对于 react-scripts < 0.2.3
如果您使用的是旧版本的 react-scripts,则可能需要添加以下配置才能将前端与后端连接起来:
$ cd client
$ yarn add http-proxy-middleware
http-proxy-middleware用于在开发过程中从我们的反应应用程序到后端应用程序创建代理。
现在,我们可以添加配置文件来设置代理,以便从前端向后端应用程序发出请求。
请记住,仅当您使用的是较旧的 React 版本(即 React-scripts < 0.2.3)时才添加此配置。
在目录 /client/src 中,添加文件 setupProxy.js,内容如下
// /client/src/setupProxy.js
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
app.use(proxy('/api/*', { target: 'http://localhost:5000' }))
}
在项目根目录中的 package.json 中,让我们添加以下运行脚本:
"client": "npm run start --prefix client",
"server": "nodemon index.js",
"dev": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\"",
"start": "node index.js"
现在你的 package.json 文件应该如下所示:
{
"name": "node-react-starter",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"client": "npm run start --prefix client",
"server": "nodemon index.js",
"dev": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\"",
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"express": "^4.17.1",
"mongoose": "^5.6.3"
},
"devDependencies": {
"concurrently": "^4.1.1",
"nodemon": "^1.19.1"
}
}
现在您可以使用以下命令运行该项目:
$ npm run dev
这将在端口 5000 上运行后端应用程序,在端口 3000 上运行前端应用程序。
您应该看到 React 应用程序在http://localhost:3000上运行
为了使我们的项目准备好投入生产,我们需要在 index.js 文件中的 app.use(bodyParser.json()) 调用之后添加以下几行:
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
const path = require('path');
app.get('*', (req,res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'))
})
}
这会将所有请求重定向到我们的前端应用程序,除非我们在此代码之前指定任何路由。
现在让我们创建一个简单的交互来查看代理连接的实际操作
在目录 /models 中添加文件 Product.js 并插入以下代码:
// /models/Product.js
const mongoose = require('mongoose');
const {Schema} = mongoose;
const productSchema = new Schema({
name: String,
description: String,
})
mongoose.model('products', productSchema);
让我们为后端 API 创建一个路由。
在目录 /routes 中添加文件 productRoutes.js 并插入以下代码:
// /routes/productRoutes.js
const mongoose = require('mongoose');
const Product = mongoose.model('products');
module.exports = (app) => {
app.get(`/api/product`, async (req, res) => {
let products = await Product.find();
return res.status(200).send(products);
});
app.post(`/api/product`, async (req, res) => {
let product = await Product.create(req.body);
return res.status(201).send({
error: false,
product
})
})
app.put(`/api/product/:id`, async (req, res) => {
const {id} = req.params;
let product = await Product.findByIdAndUpdate(id, req.body);
return res.status(202).send({
error: false,
product
})
});
app.delete(`/api/product/:id`, async (req, res) => {
const {id} = req.params;
let product = await Product.findByIdAndDelete(id);
return res.status(202).send({
error: false,
product
})
})
}
现在我们可以在 index.js 中导入模型和路由文件,如下所示:
// /index.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
// IMPORT MODELS
require('./models/Product');
const app = express();
mongoose.Promise = global.Promise;
mongoose.connect(process.env.MONGODB_URI || `mongodb://localhost:27017/node-react-starter`);
app.use(bodyParser.json());
//IMPORT ROUTES
require('./routes/productRoutes')(app);
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
const path = require('path');
app.get('*', (req,res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'))
})
}
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`app running on port ${PORT}`)
});
现在,如果我们运行项目,我们就可以使用 http ://localhost:5000/api/product向我们的简单产品 API 发出请求。
在这里,我们可以获取、插入、更新和删除产品。
回到 React 应用程序,让我们添加一个服务来向后端应用程序发出请求。
在 /client/src 文件夹中创建一个名为 services 的文件夹,并添加一个包含以下内容的文件 productService.js:
// /client/src/services/productService.js
import axios from 'axios';
export default {
getAll: async () => {
let res = await axios.get(`/api/product`);
return res.data || [];
}
}
现在让我们编辑 App.js 文件,添加一个显示产品列表的简单 UI:
// /client/src/App.js
import React, { useState, useEffect } from "react";
// SERVICES
import productService from './services/productService';
function App() {
const [products, setproducts] = useState(null);
useEffect(() => {
if(!products) {
getProducts();
}
})
const getProducts = async () => {
let res = await productService.getAll();
console.log(res);
setproducts(res);
}
const renderProduct = product => {
return (
<li key={product._id} className="list__item product">
<h3 className="product__name">{product.name}</h3>
<p className="product__description">{product.description}</p>
</li>
);
};
return (
<div className="App">
<ul className="list">
{(products && products.length > 0) ? (
products.map(product => renderProduct(product))
) : (
<p>No products found</p>
)}
</ul>
</div>
);
}
export default App;
此时,您可以使用命令 npm run dev 再次运行该应用程序,您将看到以下屏幕:
使用Postman或Insomnia等 HTTP 客户端添加一些产品。向http://localhost:5000/api/product发出 POST 请求,内容如下:
{
"name": "<product name>",
"description": "<product description here>"
}
现在,您将能够看到屏幕上呈现的产品列表,如下所示:
我希望您会发现本教程很有用,并且在接下来的几天里我将继续本教程,展示如何将这个应用程序 Docker 化。
另请查看下一篇文章,其中解释了如何将此应用程序部署到 heroku。
如果您对使用容器感兴趣,我还发表了这篇文章,解释了如何将此应用程序 dockerize 并部署到 Heroku。
源代码可以在这里找到
文章来源:https://dev.to/pacheco/my-fullstack-setup-node-js-react-js-and-mongodb-2a4k