0
votes

ReferenceError: document is not defined at Object.l.createBrowserHistory (D:\wamp\www\branches\react_ht_server\SSR_TESTING\ssr_running_bkup\node_modules\history\umd\history.development.js:5:207) at BrowserRouter (D:\wamp\www\branches\react_ht_server\SSR_TESTING\ssr_running_bkup\node_modules\react-router-dom\umd\react-router-dom.development.js:83:36) at processChild (D:\wamp\www\branches\react_ht_server\SSR_TESTING\ssr_running_bkup\node_modules\react-dom\cjs\react-dom-server.node.development.js:3353:14) at resolve (D:\wamp\www\branches\react_ht_server\SSR_TESTING\ssr_running_bkup\node_modules\react-dom\cjs\react-dom-server.node.development.js:3270:5) at ReactDOMServerRenderer.render (D:\wamp\www\branches\react_ht_server\SSR_TESTING\ssr_running_bkup\node_modules\react-dom\cjs\react-dom-server.node.development.js:3753:22) at ReactDOMServerRenderer.read (D:\wamp\www\branches\react_ht_server\SSR_TESTING\ssr_running_bkup\node_modules\react-dom\cjs\react-dom-server.node.development.js:3690:29) at Object.renderToString (D:\wamp\www\branches\react_ht_server\SSR_TESTING\ssr_running_bkup\node_modules\react-dom\cjs\react-dom-server.node.development.js:4298:27) at eval (webpack:///./server/index.js?:16:184) at Layer.handle [as handle_request] (D:\wamp\www\branches\react_ht_server\SSR_TESTING\ssr_running_bkup\node_modules\express\lib\router\layer.js:95:5) at next (D:\wamp\www\branches\react_ht_server\SSR_TESTING\ssr_running_bkup\node_modules\express\lib\router\route.js:137:13)

index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { BrowserRouter as Router } from "react-router-dom";

ReactDOM.hydrate(
  <React.StrictMode>    
      <App />    
  </React.StrictMode>,
  document.getElementById("root")
);

App.js

import React from 'react';
import { BrowserRouter as Router, Route, Routes, Link} from "react-router-dom";

import Home from './Home';
import About from './About';

export default () => {
  return ( 
   <Router>
    <nav>
        <Link to="/"> Home </Link>
        <Link to="/about"> About </Link>
        <Link to="/product"> Product </Link>
    </nav>    
     <Routes>
       <Route exact path="/" component={Home} />
       <Route path="/about" component={About} />      
     </Routes>
   </Router>
  );
};

webpack.server.js

const path = require('path');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  entry: './server/index.js',

  target: 'node',

  externals: [nodeExternals()],

  output: {
    path: path.resolve('server-build'),
    filename: 'index.js'
  },
mode: 'development',
  module: {
    rules: [
      {
        test: /\.js|jsx$/,
        use: 'babel-loader',
        exclude: /(node_modules|bower_components)/,
      },
      {
        test: /\.css$/i,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.link\.css$/i,
        use: [
          { loader: "style-loader", options: { injectType: "linkTag" } },
          { loader: "file-loader" },
        ],
      },
    ]
  }
};

package.json

{
  "name": "httpdocs",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.15.1",
    "@testing-library/react": "^11.2.7",
    "@testing-library/user-event": "^12.8.3",
    "express": "^4.17.1",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-router-dom": "^6.0.2",
    "react-scripts": "4.0.3",
    "request": "^2.88.2",
    "web-vitals": "^1.1.2"
  },
  "scripts": {
    "dev:build-server": "NODE_ENV=development webpack --config webpack.server.js --mode=development -w",
    "dev:start": "nodemon ./server-build/index.js",
    "dev": "npm-run-all --parallel build dev:*",
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@babel/core": "^7.16.0",
    "@babel/preset-env": "^7.16.4",
    "@babel/preset-react": "^7.16.0",
    "nodemon": "^2.0.15",
    "npm-run-all": "^4.1.5",
    "webpack-cli": "^3.3.12",
    "webpack-node-externals": "^1.7.2"
  }
}
1
when are you getting this error? when running tests? - TheWuif
getting this error when run command: npm run dev - user3300505
why do you want to create a custom webpack config instead of just using the react-scripts start? - TheWuif

1 Answers

0
votes

I'm not sure what your express routing looks like, so I am not sure if this will help you. But my issue was with using nested Router components. StaticRouter counts as a Router as well apparently despite the documentation examples on react-router-dom's nesting theirs.

So assuming you have an express SSR route that looks similar to this:

server.get('/*', (req, res) => {
  const app = ReactDOMServer.renderToString(
    <StaticRouter location={req.url}>
      <App />
    </StaticRouter>
  );
  const indexFile = path.resolve('./build/index.html');

  fs.readFile(indexFile, 'utf8', (err, data) => {
    if (err) {
      console.error('Something went wrong:', err);
      return res.status(500).send('Oops, better luck next time!');
    }

    return res.send(data.replace('<div id="root"></div>', `<div id="root">${app}</div>`));
  });
});

You need to make sure your application that is being rendered does not also contain a BrowserRouter or a Router component. Here is my main root App component as an example. I have commented out the lines that were causing me to get this error.

function App(props) {
  return (
    /*<Router>*/
      <div className='App'>
        <GlobalHeader />
        <Container>
          <Row>
            <Col md={12}>
              <div className='wrapper'>
                <Routes>
                  <Route exact path='/' element={<Landing />} />
                  {/* <Route path='/download' component={Download} />
                   <Route path='/account/create' component={SignUp} />
                   <Route path='/skillcalc/:skill' component={SkillCalculator} /> */}
                </Routes>
              </div>
            </Col>
          </Row>
        </Container>
      </div>
    /*</Router>*/
  );
}