如何配置create-react-app项目适配EJS模板替代index.html?
Hey there! I totally get the confusion—create-react-app (CRA) hides its webpack config by default, which makes this sort of customization feel tricky at first. Let’s walk through exactly how to get your React root component embedded in an EJS file in your Express app’s views folder.
Step 1: Access Webpack Config Without Ejecting
First, you don’t have to run npm run eject (which is irreversible). Instead, use react-app-rewired to override CRA’s config safely:
- Install the required packages:
npm install react-app-rewired customize-cra --save-dev - Update your
package.jsonscripts to usereact-app-rewiredinstead ofreact-scripts:"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test", "eject": "react-scripts eject" } - Create a
config-overrides.jsfile in your CRA project root. This is where you’ll tweak webpack settings later.
Step 2: Configure React to Work with EJS
The goal is to build your React app in a way that lets you mount it to an element in your EJS template. Here are two solid approaches:
Option A: Build as a UMD Bundle (For Flexible Mounting)
Add this to your config-overrides.js to adjust the webpack output:
const { override, adjustWebpackConfig } = require('customize-cra'); module.exports = override( adjustWebpackConfig((webpackConfig) => { // Set output to UMD so we can access React components globally or via imports webpackConfig.output.libraryTarget = 'umd'; webpackConfig.output.library = 'MyReactApp'; return webpackConfig; }) );
Then, in your React src/index.js, make sure you’re mounting to a target element that will exist in your EJS:
import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; // Check if the root element exists before mounting (prevents errors in non-EJS contexts) const rootElement = document.getElementById('react-root'); if (rootElement) { const root = ReactDOM.createRoot(rootElement); root.render(<App />); }
Option B: Keep CRA’s Default Build (Simpler for Most Cases)
If you don’t need a UMD bundle, just keep CRA’s default build setup. After running npm run build, you’ll get static assets in the build folder. We’ll reference these directly in your EJS file.
Step 3: Set Up Express & EJS Template
- In your Express app, make sure EJS is configured as the view engine:
const express = require('express'); const app = express(); app.set('view engine', 'ejs'); app.set('views', './views'); // Point to your views folder // Serve CRA's build assets as static files app.use(express.static('./client/build')); - Create your EJS file in the
viewsfolder (e.g.,views/main.ejs), and add the root element where React will mount, plus references to your CRA build files:<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>My E-Commerce Site</title> <!-- Import CRA's compiled CSS --> <link rel="stylesheet" href="/static/css/main.[contenthash].css"> </head> <body> <!-- Your existing EJS content goes here --> <h1>Welcome to My Store</h1> <!-- React will mount here --> <div id="react-root"></div> <!-- Import CRA's compiled JS --> <script src="/static/js/main.[contenthash].js"></script> </body> </html> - Add a route in Express to render this EJS file:
app.get('/', (req, res) => { res.render('main'); });
Step 4: Development Workflow Tips
- Proxy API Requests: To avoid CORS issues during development, add a proxy to your CRA
package.json:"proxy": "http://localhost:3001" // Replace with your Express server port - Hot Reload: When running
npm startin CRA, changes will hot-reload, and the React app will still mount to your EJS element as long as your Express server is serving the EJS file (you’ll need to refresh the browser if you change EJS content, though).
That’s it! You’ll now have your React app embedded directly in your EJS template, working seamlessly with your Express backend.
内容的提问来源于stack exchange,提问作者daed dadad

