部署在Heroku的MERN应用无法获取MongoDB数据求助
Heroku部署MERN应用数据获取失败问题排查
本地环境下MERN应用与MongoDB均运行正常,但部署到Heroku后,其他设备访问网页时出现数据错误,报错信息:
Failed to load resource: net:: ERR_Connection_Refused localhost:8000/api/ads:1
已完成的配置
- MongoDB Atlas设置通用网络访问为
0.0.0.0/0 - Heroku中配置了环境变量
相关代码与环境变量
server.js代码
const express = require('express'); const mongoose = require('mongoose'); const cors = require('cors'); const path = require('path'); const session = require('express-session'); const dotenv = require('dotenv'); const MongoStore = require('connect-mongo'); const bcrypt = require('bcryptjs'); // set dotenv dotenv.config(); // import routes const noticesRoutes = require('./routes/notices.routes'); const authRoutes = require('./routes/auth.routes'); const app = express(); /* MIDDLEWARE */ app.use(cors()); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(session({ secret: bcrypt.hashSync('pass', 8), store: MongoStore.create({ mongoUrl: process.env.DB_URL, collection: 'sessions' }), resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV == 'production', }, })) // access to storage folder app.use(express.static(path.join(__dirname, '/client/build'))); app.use(express.static(path.join(__dirname, '/public'))); app.use(express.static(path.join(__dirname, '/uploads/'))); // use routes app.use('/api', noticesRoutes); app.use('/auth', authRoutes); // error status app.use((req, res) => { res.status(404).send('404 not found...'); }) // React website app.get('*', (req, res) => { res.sendFile(path.join(__dirname + '/client/build/index.html')); }); /* MONGOOSE */ const NODE_ENV = process.env.NODE_ENV; let dbUri = ''; const password = process.env.PASSDB; if(NODE_ENV === 'production') dbUri = 'mongodb+srv://MarcinEden:' + password + '@cluster1.sg1w6lh.mongodb.net/RealEstateBoard?retryWrites=true&w=majority'; else dbUri = 'mongodb+srv://MarcinEden:' + password + '@cluster1.sg1w6lh.mongodb.net/RealEstateBoard?retryWrites=true&w=majority'; mongoose.connect(dbUri, { useNewUrlParser: true, useUnifiedTopology: true }); const db = mongoose.connection; db.once('open', () => { console.log('Successfully connected to the database'); }); db.on('error', err => console.log('Error: ' + err)); /* START SERVER */ const port = process.env.PORT || 8000; app.listen(port, () => { console.log('Server is running on port: '+ port); });
.env文件环境变量
NODE_ENV = production DB_URL = mongodb+srv://MarcinEden:pass@cluster1.sg1w6lh.mongodb.net/RealEstateBoard?retryWrites=true&w=majority
解决思路
修正前端API请求地址
报错显示请求指向localhost:8000/api/ads,说明前端硬编码了本地地址。生产环境需改为动态地址:- 开发环境用
http://localhost:8000 - 生产环境用相对路径(或空字符串),让请求自动指向Heroku应用域名
- 开发环境用
补全缺失的环境变量
server.js中用到了process.env.PASSDB,但当前.env和Heroku配置中未设置该变量,需在Heroku控制台添加PASSDB变量,值为MongoDB Atlas的数据库密码优化MongoDB连接逻辑
代码中同时存在DB_URL环境变量和手动拼接连接字符串的逻辑,冗余且易出错。建议直接使用process.env.DB_URL作为连接地址:mongoose.connect(process.env.DB_URL, { useNewUrlParser: true, useUnifiedTopology: true });验证Heroku环境变量生效状态
在终端执行heroku config,确认NODE_ENV、DB_URL、PASSDB三个变量均已正确配置调整CORS配置(可选)
生产环境可限定CORS origin为Heroku应用域名,避免跨域问题:app.use(cors({ origin: process.env.NODE_ENV === 'production' ? 'https://你的Heroku应用域名.herokuapp.com' : 'http://localhost:3000', credentials: true }))
内容的提问来源于stack exchange,提问作者MarcinB
相关产品推荐
相关产品推荐

