I’m trying to create isomorphic react app. This is my current code:
server.js
<code>import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom/server';
import dotenv from 'dotenv';
import mongoose from 'mongoose';
import App from './components/App';
import routes from '../routes/routes.js';
import path from 'path';
dotenv.config();
mongoose.connect(process.env.MONGODB_URI)
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Could not connect to MongoDB', err));
const app = express();
app.use(express.json());
app.use('', routes);
app.use(express.static(path.resolve(__dirname, 'public')));
app.get('/*', (req, res) => {
const context = {};
const appString = renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your App</title>
<link rel="stylesheet" type="text/css" href="/styles.css">
</head>
<body>
<div id="root">${appString}</div>
<script src="/bundle.js"></script>
</body>
</html>
`;
res.send(html);
});
app.listen(3000, () => console.log('Server is running on port 3000'));
</code>
<code>import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom/server';
import dotenv from 'dotenv';
import mongoose from 'mongoose';
import App from './components/App';
import routes from '../routes/routes.js';
import path from 'path';
dotenv.config();
mongoose.connect(process.env.MONGODB_URI)
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Could not connect to MongoDB', err));
const app = express();
app.use(express.json());
app.use('', routes);
app.use(express.static(path.resolve(__dirname, 'public')));
app.get('/*', (req, res) => {
const context = {};
const appString = renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your App</title>
<link rel="stylesheet" type="text/css" href="/styles.css">
</head>
<body>
<div id="root">${appString}</div>
<script src="/bundle.js"></script>
</body>
</html>
`;
res.send(html);
});
app.listen(3000, () => console.log('Server is running on port 3000'));
</code>
import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter } from 'react-router-dom/server';
import dotenv from 'dotenv';
import mongoose from 'mongoose';
import App from './components/App';
import routes from '../routes/routes.js';
import path from 'path';
dotenv.config();
mongoose.connect(process.env.MONGODB_URI)
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Could not connect to MongoDB', err));
const app = express();
app.use(express.json());
app.use('', routes);
app.use(express.static(path.resolve(__dirname, 'public')));
app.get('/*', (req, res) => {
const context = {};
const appString = renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Your App</title>
<link rel="stylesheet" type="text/css" href="/styles.css">
</head>
<body>
<div id="root">${appString}</div>
<script src="/bundle.js"></script>
</body>
</html>
`;
res.send(html);
});
app.listen(3000, () => console.log('Server is running on port 3000'));
webpack.config.js
<code>const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = [
{
// Client bundle configuration
entry: './src/client.js',
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
},
devServer: {
publicPath: '/',
contentBase: path.join(__dirname, 'public'),
compress: true,
port: 9000,
hot: true,
},
},
{
// Server bundle configuration
entry: './src/server.js',
target: 'node',
externals: [nodeExternals()],
output: {
path: path.resolve(__dirname, 'build'),
filename: 'server.js',
},
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
},
},
];
</code>
<code>const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = [
{
// Client bundle configuration
entry: './src/client.js',
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
},
devServer: {
publicPath: '/',
contentBase: path.join(__dirname, 'public'),
compress: true,
port: 9000,
hot: true,
},
},
{
// Server bundle configuration
entry: './src/server.js',
target: 'node',
externals: [nodeExternals()],
output: {
path: path.resolve(__dirname, 'build'),
filename: 'server.js',
},
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
},
},
];
</code>
const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = [
{
// Client bundle configuration
entry: './src/client.js',
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
},
devServer: {
publicPath: '/',
contentBase: path.join(__dirname, 'public'),
compress: true,
port: 9000,
hot: true,
},
},
{
// Server bundle configuration
entry: './src/server.js',
target: 'node',
externals: [nodeExternals()],
output: {
path: path.resolve(__dirname, 'build'),
filename: 'server.js',
},
module: {
rules: [
{
test: /.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
},
},
];
App.jsx
<code>import React from 'react';
import {BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './Home';
import Archive from './Archive';
const App = () => (
<>
<Router>
<Routes>
<Route path="/" element={ <Home /> } />
<Route path="/archive" element={ <Archive /> } />
</Routes>
</Router>
</>
);
export default App;
</code>
<code>import React from 'react';
import {BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './Home';
import Archive from './Archive';
const App = () => (
<>
<Router>
<Routes>
<Route path="/" element={ <Home /> } />
<Route path="/archive" element={ <Archive /> } />
</Routes>
</Router>
</>
);
export default App;
</code>
import React from 'react';
import {BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './Home';
import Archive from './Archive';
const App = () => (
<>
<Router>
<Routes>
<Route path="/" element={ <Home /> } />
<Route path="/archive" element={ <Archive /> } />
</Routes>
</Router>
</>
);
export default App;
client.js
<code>import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
if (typeof window !== 'undefined') {
const root = document.getElementById('root');
if (root) {
ReactDOM.createRoot(root).render(<App />);
}
}
</code>
<code>import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
if (typeof window !== 'undefined') {
const root = document.getElementById('root');
if (root) {
ReactDOM.createRoot(root).render(<App />);
}
}
</code>
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
if (typeof window !== 'undefined') {
const root = document.getElementById('root');
if (root) {
ReactDOM.createRoot(root).render(<App />);
}
}
After I run npm start
I get Referrence Error: document is not defined. I think I understand the problem, but I cannot solve this.
I’ve got also problem with rendering. I feel like there is a problem with my server.js app.get problem.
I tried with checking every import/export and tried with
typeof window !=='undefined'
but nothing works.
New contributor
user24872813 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.