Express+React全栈应用部署的文件结构及合并相关技术咨询
Great questions! Let's break this down one by one to clarify your confusion around deploying and structuring your Express + React app:
1. Do I have to merge the two projects to deploy to Heroku/AWS?
No, you don't have to merge them—you have two valid options:
- Separate deployment: Deploy the React frontend as a static site (e.g., AWS S3 + CloudFront, Netlify, or even a standalone Heroku app) and the Express backend as a separate API service. You'll just need to configure CORS on the backend to allow requests from your frontend's domain, and update the frontend's API base URL to point to the deployed backend.
- Merged deployment: Bundle the React frontend's production build into the Express app, so the backend serves both the API endpoints and the static frontend files. This is simpler for single-domain deployments and works well on platforms like Heroku where you can run a single app instance.
2. Why use create-react-app and express-generator if they don't create a full-stack structure?
These tools are designed for separation of concerns and focused development workflows:
create-react-appoptimizes for frontend development: it handles bundling, hot reloading, and React-specific tooling out of the box, so you can focus on building UI without configuring Webpack/Babel manually.express-generatorsets up a minimal, production-ready Express backend structure, with routing, middleware, and server configuration pre-configured for API development.
Separating the projects during development lets frontend and backend teams work independently, test their parts in isolation, and iterate faster. Merging is only a deployment consideration, not a development requirement.
3. How to merge the two projects (adjusting file structure only)?
Here's a step-by-step guide since your apps already communicate correctly:
- Move the React project into the Express project: Create a
clientfolder in your Express root directory, then copy all files from your React project into thisclientfolder. - Configure Express to serve static frontend files: In your Express app's main file (usually
app.js), add code to serve the React build output:const path = require('path'); // Serve static files from the React build folder app.use(express.static(path.join(__dirname, 'client/build'))); // Handle SPA routing: redirect all non-API requests to React's index.html app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'client/build', 'index.html')); }); - Verify the structure: Your merged project will look like this:
your-app/ - bin/ - routes/ - client/ - src/ - public/ - package.json - app.js - package.json
4. How to adjust package.json after merging?
You'll need to update the Express project's package.json to handle frontend builds and development workflows:
- Production setup: Add a
buildscript that installs frontend dependencies and builds the React app, then yourstartscript runs the Express server (which will serve the static build files):"scripts": { "start": "node ./bin/www", "build": "cd client && npm install && npm run build", "heroku-postbuild": "npm run build" // For Heroku, this runs automatically on deploy } - Development setup: If you want to run both apps concurrently during development (with hot reloading), install
concurrentlyfirst (npm install --save-dev concurrently), then add adevscript:
Now you can run"scripts": { "start": "node ./bin/www", "build": "cd client && npm install && npm run build", "dev": "concurrently \"npm start\" \"cd client && npm start\"", "heroku-postbuild": "npm run build" }npm run devto start both the Express backend and React frontend at the same time.
Best Practices for Express + React (No MongoDB) File Structure
For a clean, maintainable full-stack structure (similar to MERN but without MongoDB), here's a recommended setup:
your-fullstack-app/ - client/ # React frontend (from create-react-app) - src/ - components/ # Reusable UI components - pages/ # Page-level components (e.g., Home.js, About.js) - services/ # API call functions (e.g., apiClient.js) - hooks/ # Custom React hooks - App.js - index.js - public/ - package.json - server/ # Express backend (can be the express-generator output) - bin/ - routes/ # API routes (e.g., users.js, posts.js) - middlewares/ # Custom middleware (e.g., auth.js, errorHandler.js) - controllers/ # Route logic handlers (e.g., userController.js) - utils/ # Helper functions (e.g., validation.js) - app.js - package.json - package.json # Root package.json for global scripts "scripts": { "dev": "concurrently \"cd server && npm run dev\" \"cd client && npm start\"", "build": "cd client && npm run build", "start": "cd server && npm start" }
This structure keeps frontend and backend code separated but under one repository, making it easy to manage both parts while maintaining clear boundaries.
内容的提问来源于stack exchange,提问作者Quabby

