Css Files in Meteor React SSR

Hello dear friends.
I am doing SSR for my project. My project works with the following objects:

  • meteor 1.11

  • react 16.13

  • React Router 5

In some of my components, the css file is imported .

like this in Header Componetnet :

import './Header.css';

But despite these imports, the software gets an error.
like this error :

Please Guide Me .
How can I use CSS files?

I also used the following code for SSR on the server and client side .

Server :

import React from "react";
import { onPageLoad } from "meteor/server-render";
import { renderToString } from "react-dom/server";
import { ServerStyleSheet } from "styled-components"

import ServerRoutes from '../../Routes/Server-Routes';

onPageLoad(sink => {
  const sheet = new ServerStyleSheet();
  const html = renderToString(sheet.collectStyles(
    <ServerRoutes location={sink.request.url} />
  ));

  sink.renderIntoElementById("App", html);
  sink.appendToHead(sheet.getStyleTags());
});

Client :

import React from 'react';
import ReactDOM from 'react-dom';
import { onPageLoad } from 'meteor/server-render';

onPageLoad(async sink => {
  const Routes = (await import('../../Routes/Client-Routes')).default;
  ReactDOM.hydrate(
    <Routes />,
    document.getElementById('App')
  );
});

@filipenevola @storyteller @stolinski and other firends .

It has been a year since this issue was opened.
Has anyone really addressed this important issue?
Maybe that’s why so many people can’t use meteor .

Sorry, but I don’t use SSR in my apps at the moment so I don’t have any idea.

1 Like

We’ll probably need more information about how your SSR code is set up. I’m not sure if the built in Meteor css package actually supports it or not - I use fourseven:scss

I will say though that I typically don’t import my CSS in to the module this way, because if you import it to the CSS file directly, you get instant CSS refresh during development, instead of a full client rebuild and refresh (and server rebuild if you have that module linked to the server bundle).

Maybe try switching to fourseven:scss and import everything from a main .scss file (so that they get bundled - I think by default the regular css bundler will output actual import statements, instead of making a bundle). I typically still use a CSS module style file layout, but import everything directly from a main module in the client folder. You can still use vanilla CSS in fourseven:scss if you prefer, and it’ll get bundled.

Here’s an example main.scss file from a recent relatively fresh project:

@import "./theme";
@import "./global";
@import "./layout";

// :TODO: Find a way to gather these automatically
@import "{}/imports/ui/layouts/MainLayout";
@import "{}/imports/ui/home/HomeScreen";

(fourseven:scss won’t eagerly bundle scss files outside of the /client folder at all, and won’t bundle files inside the /client bundle if they start with underscore _ - so you can control the bundle order.)

1 Like

I have now tested this method :
I prevented imports on the server by placing this condition when importing :

\\ In the Layout Component : 

if (Meteor.isClient) {
    import 'bootstrap/dist/css/bootstrap.min.css';
    import './Pages.css';
}

with this way, when ssr, css files are not rendered from server .
But the problem is that when the user enters the site, he encounters styleless elements.
Although it helps SEO a lot, but the other user does not have a good experience.

What do you think about this method?

This is what I do too—however not in an SSR context. Google’s Lighthouse started flagging this from SEO perspective, probably because Lighthouse, and, by extension, the Google crawler don’t see a Meteor app as an SPA (especially not in my case, as I serve Googlebot with prerendered snapshots from redis).

The verdict is that the single css bundle is bad practice, because the page does a blocking load of tons of css that it doesn’t even need. I’m not sure though how much this adversely affects SEO in the algorithms in Google Search. Because of this, I for my part plan to go away from the single main css and move towards individually imported css files.

2 Likes

This never made much sense to me. My total CSS package is generally under 40K, and it’s only 1 extra request. On PixStori it’s only around 7.8KB - though much of the app CSS framework is JSS from Material-UI - even though I’ve been actively moving away from JSS overrides in component code - at runtime, it’s SO SLOW. My apps start and run noticeably faster if I do it this way. If it’s really that much of a concern for Google, I suppose I could inline the CSS content in the HTML, or send an http/2 header or something. I guess in some sites where they just have a ton of extra CSS that might be an issue, but my apps aren’t typically overloaded that way. ymmv.

1 Like

JSS is the worst idea I have encountered in a very long time, its apparent popularity never ceases to amaze me. I am totally fine with a single CSS bundle; it’s Lighthouse/Google who’s complaining about it, not me. Especially in the context of an SPA a single cacheable CSS makes totally sense – far more so than inline CSS in html head or similar. Thing is, I feel forced to dance to Google Search’s tune. I’m just looking for a solution to avoid my app getting penalized by Google for what they like to see as “bad practice”.

The new core web vitals introduced by Google months ago will be affected.

  1. The blocking css call affects the loading of the major content of the site.

  2. One way to solve this is to defer the loading of the css file. But that will affect another metric which is the shifting of elements in the page as they are loading which is a bad experience

The solution we did is inlining css for the initial page loaded by the user while deferring the css file for the rest of the SPA

1 Like

I was going to say - just inline the one main CSS bundle to the HTML page output, and you’re done. But I don’t know how to do that in Meteor…

Yeah, JSS is not my favorite - I honestly keep looking for a way to simply remove it from Material UI - I wish they’d get rid of that thing… Material UI has a lot of value though, so I tolerate it. But I don’t use it myself.

1 Like

Given these new core web vitals, Meteor’s single blocking css bundle is becoming increasingly questionable. I’m wondering about Google’s reluctance to acknowledge SPAs as being different in many aspects from traditional web applications, but realistically, when it comes to policy making, Google has the status of a deity that just doesn’t listen to ordinary mortals’ earthly concerns.

Following the principle of 'if the mountain will not come to Muhammad, then Muhammad must go to the mountain, we may have to find a suitable solution to be built into Meteor, along the lines of the solution you mentioned.

We are also doing AMP. And Google has a limit to the “size” of the css that you can inline :sweat_smile:

If anybody is interested, @wildhart has a fantastic solution to this. That is what we followed for our implementation

Pre-rendered landing pages with Critical CSS

1 Like

Of course they do…

Why didn’t you mention ways to use CSS in JS, such as styled- Components? It’s so cool, you have to try it if you get the chance

1 Like

It breaks prerendering completely.

I use JSS in some Material-UI projects to a minimum extent - I don’t like it, as it takes longer for page refreshes during development, and there is a runtime overhead, even in production (sometimes quite noticeable overhead). I prefer to just use SCSS directly.

BTW, it doesn’t break SSR, but you have to wire it up in your SSR code. (There are similar tutorials for styled components.)

I don’t have SSR, just prerendering with a headless Chrome. In that configuration JSS hopelessly breaks everything.