Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Server Side Rendering with Sass

As i have searched through the previous but could not find any relevant / solved issues on this so I ask...

Current stack: React, express/node, Sass, Webpack, Sass.

I have a question specific to the Styling of pages before server sends them to the browser.

Styling is working perfectly in the browser and by I mean when the pages are being navigated via browser router, all the styling works. However, I need to figure out a way to inject custom Sass styles to the page before the Server sends the page to the browser.

Current behavior: I access any page from the browser, I get serve the page with correct styling BUT there is a minor delay to get the correct styling in place to appear on the page. If view in slow motion, page appears without styling (because the server sent the page with no styling) and then browser takes over with correct styling.

I have tried webpack to generate all styles in a separate file but I can't seem to link this file to page before server sends it to the browser.

Any help / feedback will be appreciated?

server.js(route handler)

app.get('*', (req, res) => {
  const store = createStore();

  const promises = matchRoutes(Routes, req.path).map(({ route }) => {
    return route.loadData ? route.loadData(store) : null;
});

Promise.all(promises)
.then(() => {
  const context = {};
  const content = renderer(req, store, context);

  if (context.notFound) res.status(404);

  res.send(content);
 });
});

const PORT = process.env.PORT || 3000;

renderer.js

import React from 'react';
import { renderToString } from 'react-dom/server';
import { StaticRouter, matchPath } from 'react-router-dom';
import { Provider } from 'react-redux';
import { renderRoutes } from 'react-router-config';
import serialize from 'serialize-javascript';
import Routes from '../client/Routes';

export default (req, store, context) => {

  // req.path is the url that the user is trying to access
  const content = renderToString(
  <Provider store={store}>
   <StaticRouter location={req.path} context={context}>
    <div>
      { renderRoutes(Routes) }
    </div>
   </StaticRouter>
 </Provider>
);

return `
  <html>
    <head>
      <link rel="stylesheet" href="../../public/styles.css">
    </head>
    <body>
      <div id='app'>${content}</div>
      <script>
        window.INITIAL_STATE = ${serialize(store.getState())}
      </script>
      <script src="bundle.js"></script>
    </body>
  </html>
`;
};

webpack.config.js (I omitted the rest of config since its not relevant)

const extractSass = new ExtractTextPlugin({
  filename: "styles.css",
  disable: process.env.NODE_ENV === "development"
});

module: {
rules: [{
    test: /\.scss$/,
    use: extractSass.extract({
        use: [{
            loader: "css-loader"
        }, {
            loader: "sass-loader"
        }],
        // use style-loader in development
        fallback: "style-loader"
    })
  }]
},
plugins: [ extractSass ],

This gives me a styles.css file in my /build folder. How can i link this to my html. If i try to throw a <link> tag the browser does not recognize the file.

like image 527
Ash Avatar asked Apr 21 '18 19:04

Ash


People also ask

Can you do server-side rendering IN React?

Yes! This is where server-side rendering for React comes in. In this article, I want to introduce you to server-side rending (SSR) with React, reasons to use it, and some popular frameworks for rendering React on the server side.

Can you use React with sass?

Can I use Sass? If you use the create-react-app in your project, you can easily install and use Sass in your React projects. Now you are ready to include Sass files in your project!

Does React use SSR or CSR?

In fact, it was Facebook's release of the React library that popularised a CSR approach to applications by making it more technologically accessible. On the other hand, a web-based app serving mainly static content, like this website, would be expected to opt for an SSR approach.

Which React tool is used for server-side rendering?

Next. js is used for server side rendering of react application . React along with other framework like angular and vue. js are traditional client side framework ,they run in browser but there are technology to run this framework on server side, and next.


1 Answers

I finally solved this issue by creating another route handler.

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

My webpack compiles a styles.css file which gets put in the /public folder. Please note i changed the path of my styles file in webpack to this: ../public/styles.css

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

Above statement ^^^ makes the styles.css file accessible and finally styles are applied by supplying the below <link> tag in the response of server to the browser.

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

If anyone else have a better solution, I would love to get feedback.

like image 134
Ash Avatar answered Oct 01 '22 15:10

Ash