'SSR React APP with Static router on express
I am trying to SSR a react application made from scratch on an express server. I am using Static Router. The html loads into browser and routing works but css and js bundle do not load. In network I get a 200 for js and css but the type of file is html. This is my first time rendering a React App with a router, server side. The app works perfectly when rendered client side. I only have one WebPack Config File
The error I am getting in terminal when running the ssr app is
No routes matched location "/static/client.js"
No routes matched location "/static/client.7d7fcbbf9b1c53c6d706.css"
No routes matched location "/static/client.7d7fcbbf9b1c53c6d706.css"
If anyone has any idea on how I would be able to fix this issue it would be greatly appreciated! Thank you for your time.
Express Config
const path=require('path');
const fs=require('fs');
const express=require('express');
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const router = express.Router()
import {StaticRouter} from 'react-router-dom/server'
import Rout from '../src/Menu/router';
const app = express()
const PORT = 9001
const serverrender = (req, res, next)=>{
const aa = ReactDOMServer.renderToString(<StaticRouter location={req.url}><Rout/></StaticRouter>)
fs.readFile(path.resolve('./assets/index.html'), 'utf-8',(err, data) => {
if(err){
console.log(err)
}
return res.send(data.replace('<div id="root"></div>',
`<div id="root">${aa}</div>`))
})
}
router.use(express.static(path.resolve(__dirname, '..', '/assets/static')))
router.use('/', serverrender)
app.use(router)
app.listen(PORT, ()=>{
console.log(`${PORT}`)
})
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports={
mode: 'production',
entry:{
client: './src/index.js'
},
output:{
path: path.resolve(__dirname, 'assets'),
filename:"static/[name].js"
},
module:{
rules:[
{
test: /\.js$/, exclude: /node_modules/, loader: "babel-loader",
options: {
// attach the presets to the loader (most projects use .babelrc file instead)
presets: ["@babel/preset-env", "@babel/preset-react"]
}
},
{test: /\.css$/i, use: [MiniCssExtractPlugin.loader,'css-loader']},
{test: /\.(png|jpe?g|gif)$/i, use: ['file-loader']},
]
},
plugins: [new HtmlWebpackPlugin({ template: path.resolve(__dirname, 'src', 'index.html') }),
new MiniCssExtractPlugin({ // [2]
filename: 'static/[name].[hash].css'
})],
devServer: {
//hot: true,
//historyApiFallback: true,
},
}
{
"dependencies": {
"@babel/register": "^7.17.0",
"axios": "^0.24.0",
"express": "^4.17.2",
"ignore-styles": "^5.0.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-responsive": "^9.0.0-beta.6",
"react-router-dom": "^6.2.1"
},
"devDependencies": {
"@babel/core": "^7.16.0",
"@babel/plugin-transform-runtime": "^7.16.5",
"@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"babel-loader": "^8.2.3",
"css-loader": "^6.5.1",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.5.0",
"isomorphic-style-loader": "^5.3.2",
"mini-css-extract-plugin": "^2.5.3",
"style-loader": "^3.3.1",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.6.0"
},
"scripts": {
"start": "webpack-dev-server --open",
"build": "webpack",
"ssr": "node server/index.js"
}
}
Solution 1:[1]
Try this, I updated your express config code
const path = require("path");
const fs = require("fs");
const express = require("express");
const React = require("react");
const ReactDOMServer = require("react-dom/server");
const router = express.Router();
import { StaticRouter } from "react-router-dom/server";
import Rout from "../src/Menu/router";
const app = express();
const PORT = 9001;
const serverrender = (req, res, next) => {
const aa = ReactDOMServer.renderToString(
<StaticRouter location={req.url}>
<Rout />
</StaticRouter>
);
fs.readFile(path.resolve("./assets/index.html"), "utf-8", (err, data) => {
if (err) {
console.log(err);
}
return res.send(data.replace('<div id="root"></div>', `<div id="root">${aa}</div>`));
});
};
// router.use(express.static(path.resolve(__dirname, '..', '/assets/static')))
// router.use('/', serverrender)
// root (/) should always serve our server rendered page
router.use("^/$", serverrender);
// other static resources should just be served as they are
router.use(
express.static(path.resolve(__dirname, "..", "/assets/static"), {
maxAge: "30d",
})
);
// any other route should be handled by react-router, so serve the index page
router.use("*", serverrender);
app.use(router);
app.listen(PORT, () => {
console.log(`${PORT}`);
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Anil Kumar |