If you want your Express ejs pages to serve your React code on the same port create the following files:
src/javascripts/views/layout.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= title %></title>
</head>
<body>
<div class="container" >
<h2>Server rendered EJS File</h2>
<div id="main">
<!--This div is where React Component Renders -->
</div>
</div>
<script src="javascripts/main.js"></script>
</body>
</html>
src/javascripts/main.js file:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './components/App'
ReactDOM.render(<App />, document.getElementById('main'))
src/javascripts/components/App.js
import React from 'react'
export default function App() {
return (
<div className="react-stuff">
<h1>My React App component</h1>
</div>
)
}
In your Express server designate the following public folder:
app.use(express.static(path.join(__dirname, 'public')))
In webpack specify that your React source code should compile from src/javascripts/main.js to pubic/javascripts/main.js:
entry: {
main: './src/javascripts/main.js'
},
output: {
path: path.resolve(__dirname, 'public'),
filename: 'javascripts/main.js',
publicPath: '/'
},
Finally, create an Express route that serves layout.ejs. Say "/" (e.g. http://localhost:8080)
Now, every time you compile your React code it will take the code in ./src/javascripts/main.js and compile/bundle it to your Express static directory (e.g. public/javascripts/main.js)
And when you request http://localhost:8080, Express will serve layout.ejs. Since layout.ejs is connected to your React bundle via the script tag which points to public/javascripts/main.js it will serve your App.js React component!
Note: The above solution is relying on an architecture where your React pages are going to be served by Express. However, if you want to create a SPA (a single page application) that is completely independent of your Express server (except perhaps for the SPA's API calls) then the solution will be different and will involve (as other answers have suggested) the use of a proxy line in your package.json.
Here also is a diagram that outlines the relationship between the different files:
