简体   繁体   中英

React Server Side Rendering with CSS (SASS)

I am trying to build an isomorphic React app, but for now I will just limit my question to the server side rendering portion. I want to render some React JS components on the server side of my application. I am able to do so with the method ReactDomServer.renderToString . However I am unable to get the CSS (or my SASS/SCSS files) to work with these components.

For the client side I can usually just use something like Webpack and the css-loader/style-loader and when I bundle the JS, the components will be correctly styled. However, I do not know how to do this on the server side. This is the error that I get when I run ts-node on my server file

body {
     ^

SyntaxError: Unexpected token '{'
    at Object.compileFunction (node:vm:360:18)
    at wrapSafe (node:internal/modules/cjs/loader:1088:15)
    at Module._compile (node:internal/modules/cjs/loader:1123:27)
...

The following are my relevant files.

src/components/App.tsx

import React from "react";
import "./App.scss"

class App extends React.Component {
    override render(): React.ReactNode {
        return (<div>THIS IS THE APP START</div>);
    }
}

export default App;

src/components/App.scss

$mycolor: red;

body {
    color: $mycolor;
}

src/server.tsx

import express from "express";
import ReactDomServer from "react-dom/server";
import App from "./Components/App";

const app = express()
const port = 3000

app.get('/', (req, res) => {
  const html = ReactDomServer.renderToString(<App />);
  res.send(html);
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
});

tsconfig.json

{
    "include": ["src/**/*"],
    "exclude": ["node_modules"],
    "compilerOptions": {
        "esModuleInterop": true,
        "moduleResolution": "Node16",
        "jsx": "react-jsx"
    }
}

package.json

{
  "name": "really",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "start": "ts-node src/server.tsx"
  },
  "dependencies": {
    "@types/node-sass": "^4.11.3",
    "@types/react": "^18.0.25",
    "@types/react-dom": "^18.0.9",
    "express": "^4.18.2",
    "node-sass": "^8.0.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "sass": "^1.56.1",
    "ts-node": "^10.9.1"
  },
  "devDependencies": {
    "typescript": "^4.9.3"
  }
}

Not sure if it possible to load the CSS before express serves the components. Another possible way might be to use webpack to bundle the server side files and load the CSS but I do not know if this will work and it feels odd to me for server side parts. Is there a way to do this without webpack or not really?

You will still need something to translate scss to css file during build time, the css file should go into a public folder and then you add link rel in the html react template

<link rel="stylesheet" href="../../public/styles.css">

you will need to serve it with express when the browser makes a call for it

app.get('/styles.css', (req, res) => {
  res.sendFile(__dirname + "/" + "styles.css");
});

or server static folder with that file present

app.use(express.static('public'));

There is no way to do this with ts-node as it doesn't have a plugin to import css or sass files (the error appears because it cannot parse the SASS syntax). You could do it with webpack which has plugins to import sass files.

However, there are already a ton of SSR frameworks like Next.js or Gatsby available which will handle all of this for you. With Next.js you can also dynamically access the request data and render something different for every request.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM