You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MERN博客非Heroku免费部署咨询:是否需合并前后端文件夹?

MERN博客免费后端部署方案及前后端结构疑问

问题描述

我搭建了一个包含client(前端)和api(后端)两个独立文件夹的MERN博客,希望部署到免费主机服务,但因Heroku自11月22日起转为收费服务,故不想使用该平台。现咨询无需依赖Heroku的后端部署流程,同时明确是否需要合并前后端文件夹?

后端核心代码(index.js)

// this is my index.js pubblished on vercel

if (process.env.NODE_ENV !== 'production') {
  require('dotenv').config({path: __dirname+'/.env'});
}
const express = require("express");
const multer = require("multer");
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const authRoute = require("./routes/auth");
const userRoute = require("./routes/users");
const postRoute = require("./routes/posts");
const categoryRoute = require("./routes/categories");
const path = require("path");

const app = express();
dotenv.config();

mongoose
  .connect(process.env.MONGO_URL, {
    useNewUrlParser: true,
    useUnifiedTopology: false,
  })
  .then(() => {
    console.log("MongoDB connected!");
  })
  .catch((err) => {
    console.log(err);
  });

app.use(express.json());

app.use("/images", express.static(path.join(__dirname, "/images")));

const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, "images");
  },
  filename: (req, file, cb) => {
    cb(null, req.body.name);
  },
});

const upload = multer({ storage: storage });
app.post("/api/upload", upload.single("file"), (req, res) => {
  res.status(200).json("File has been uploaded");
});
//endpoints
app.use("/api/auth", authRoute);
app.use("/api/users", userRoute);
app.use("/api/posts", postRoute);
app.use("/api/categories", categoryRoute);

app.get('/', (req,res)=>{
  res.json({
    "ciao":"io sono il backend",
  });
});

// static files (build of your frontend)
if (process.env.NODE_ENV === 'production') {
  app.use(express.static(path.join(__dirname, '../frontend', 'build')));
  app.get('/*', (req, res) => {
    res.sendFile(path.join(__dirname, '../frontend', 'build', 'index.html'));
  })
}

app.listen(process.env.PORT || 5000, () => {
  console.log("Listening at port 5000");
});

解答

是否需要合并前后端文件夹?

不需要强制合并,两种方案都能正常运行:

  • 分开部署:前端部署到静态托管平台,后端部署到Node.js专用平台,前端通过后端提供的域名调用API接口。这种方式前后端独立维护,更新互不影响。
  • 合并部署:利用你代码里已有的生产环境托管静态文件逻辑,把前端build产物放到后端指定目录,将整个项目(含client和api)部署到支持Node.js的平台,由后端同时提供API服务和前端静态文件访问。这种方式适合想统一管理部署流程的场景。

免费后端部署流程(以三个常用平台为例)

方案1:Vercel

  1. 将后端代码推送到GitHub/GitLab等代码仓库
  2. 登录Vercel平台,导入你的后端仓库
  3. 在项目设置的「环境变量」板块,添加MONGO_URL等项目所需的环境变量
  4. Vercel会自动识别Node.js项目,默认执行npm install && npm start完成构建启动,若有特殊需求可通过vercel.json配置自定义命令
  5. 部署完成后,平台会生成一个后端访问域名,前端配置该域名即可调用API

方案2:Railway

  1. 将后端代码推送到代码仓库,或直接在Railway平台导入本地代码
  2. 创建新的Node.js服务,关联你的后端仓库
  3. 在服务设置中添加所需环境变量
  4. 平台自动完成依赖安装和服务启动,生成访问域名

方案3:Render

  1. 登录Render平台,创建「Web Service」类型的服务
  2. 导入后端代码仓库,设置构建命令为npm install,启动命令为npm start
  3. 添加项目所需的环境变量,确认后触发部署,完成后获取访问域名

额外注意事项

  • 若选择合并部署,需确保前端build产物路径与后端代码中的配置匹配,部署前可先在本地执行前端的npm run build命令生成build文件夹,或在部署脚本中添加自动构建前端的步骤
  • 你的代码中使用了本地存储上传文件,但多数免费平台的文件系统是临时的,重启服务后文件会丢失,建议改用云存储服务托管上传的图片资源

内容的提问来源于stack exchange,提问作者Tommaso RZT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:01:12