Introduction
TL;DR
In this post we gonna deep dive into styles and Css in JS .
Lately, i receive some question about: how does Styled components works ? Why Styled is still not working in Server Components ? And so on…
So i decided to start this repository to bring some answers to these questions.
When we use <link>
and refer to a css file, the browser will download the css file and apply the styles to the page.
You can see this behavior in the 1_simple/index.html
file.
The result:
The page will render without styles, and after the browser download the css file, the styles will be applied to the page.
- -
When we use <style>
tag, the browser will apply the styles to the page.
You can see this behavior in the 1_simple/about.html
file.
The result:
The page will render with styles.
Is that the solution ? No, because we will have a lot of <style>
tags in our html file, and this is not a good practice.
- -
Before start talking about styled-components, let's talk start a new example:
You can browse the 2_clientside_render
folder, and run:
yarn
To start the server:
yarn dev
In the image below, you can see that first the browser will render the page without content.
Of course, our index.html file just have a <div id="app"></div>
.
After the browser download the javascript file, the page will be rendered with the content.
Even after build, you can see something like that:<!doctype html>
<html lang="en">
<head>
<script type="module" crossorigin src="/assets/index-44b5bae5.js"></script>
<link rel="stylesheet" href="/assets/index-48a8825f.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
Conclusion about this: The browser will render the page without content, and after the javascript file is downloaded, the page will be rendered with the content.
- ---
Let's make it more interesting, i will copy the 2_render_csr
folder to 3_render_ssr
After this, i will create a server.js to read dist folder and serve the files to the browser with server side rendering.
I had to add:
- Fastify (server)
- @fastify/static (to serve the files)
In this point, the behaviour is the same, the browser will render the page without content, and after the javascript file is downloaded, the page will be rendered with the content.
let's fix this:
I will remove some assets, because i need a the DOM Tree, chunks, etc… so i will only have the counter component and css preloaded.
lets browse the 4_preact_ssr
folder, run:
let's run:
yarn
yarn ssr
Wow, thats awesome, the page will be rendered with the content by the server side. And if you are paying attencion until now, the only thing that is missing here is the styles.
so let's add this on server side also. The POOR way to do that is injecting inline styles in the html file.
Conclusion: at this point, we understand how browser works, and how to render the page with CONTENT AND STYLE in the server side.
But, WHEN WE GONNA TALK ABOUT STYLED COMPONENTS ?
Right now, my baby padawan.
- -
Just a disclaimer:
1 - Styled components and SSR is not a good idea, because the styles will be injected in the html file, and this will make the file bigger, and the browser will take more time to download the file.
2 - Start to learn and use css modules, tailwind, etc… because you will not have a headache with SSR. Runtime styles is not a good idea for meta-framework today.
Let's browse the 5_styled_components
folder, run:
yarn
yarn dev
Note: Even using tailwind, the page will be rendered without styles.
But remember, we need to have a solid understanding about how the browser works.
How it works under the hood, or the basic things.
In this point, i will not fix whole page, but i will create 2 different component that will be rendered in the server side.
The first component will be rendered with styles, and the second will be rendered without styles.
The tradeoff here using `styled-component`:1 - When we use styled components, the styles will be injected in the html file, and this will make the file bigger, and the browser will take more time to download the file.
2 - You must use "use client". This could be confused to have "use server" here, and client there, etc…
if you remove the "use client" directive, you will see this error:
Error: createContext only works in Client Components. Add the "use client" directive at the top of the file to use it. Read more: https://nextjs.org/docs/messages/context-in-server-component
Conclusion: styled components is not a good idea for SSR. The [G]OLD way to do that is using css modules ou scss.
You will notice that downlowding the css file is faster than download the javascript file.
The css is too small and just download what you are using, not the whole styles resources.
If you are using emotion today, because you need to use css in js ( mantine or Material UI ), no problem. Dont worry about that.
Hype comes and goes, but the basics will be always the same.
"Tools cannot change how browser works, only make it easier to do something."
- Castro, Alexandro (aka me)
Note:
In a Next.js discussion, there is a comment that talk about experimental features, and one of them is `optimizeCss`, so let's try this.
They use this package:
https://www.npmjs.com/package/critters
This package will extract the critical css and inject in the html file.
I really think this have issues yet, so i will not use this approach.
References:
https://github.com/fastify/fastify-static
https://preactjs.com/guide/v10/getting-started
https://shubhamverma.me/blog/server-side-rendering-of-tailwind-css-styles-in-next-js
https://blog.mikelramos.com/posts/optimizing-css-delivery-nextjs
https://nextjs.org/docs/app/building-your-application/styling/css-modules