Loading css into Next.js the right way - css

I have read a few different sources about this and according to the official docs:
Consequently, there are a bunch of practical issues to consider with
traditional CSS-file-based styling (especially with SSR), so we
suggest avoiding this method when styling for Next.js.
Instead we recommend CSS in JS, which you can use to style individual
components rather than importing CSS files.
Next.js comes preloaded with a CSS in JS framework called styled-jsx,
specifically designed to make your life easier. It allows you to write
familiar CSS rules for your components; rules will have no impact on
anything other than the components (not even child components).
But I have seen tutorials out there showing that you can load in css files like:
import Head from "next/head";
const Layout = props => (
<>
<Head>
<link href="theme.css" rel="stylesheet" />
</Head>
<Header />
<main>{props.children}</main>
</>
);
This would make my life much easier because I am using an html theme which I am porting to a next.js project. And the theme.css file is 23000 lines of code long. Imagine now I had to try and find all those css classes, extract them and put them into their individual components. That would take forever!
So, the actual question is, is it really that bad to just pull in the entire stylesheet and use it 'globally'?

I am actually trying to figure out too the best way to load css in a next js project, I decided recently to import all my pages style sheets in the _app.js but then i found that my lighthouse score went from 70% to 42%. I used always the jsx approach and i guess it is much better for better performance.
like this for example :
const ReVerifyLink = () => (
<div>
<p>
Click
<Link href={{ pathname: routes.RE_VERIFY }}>
<a>here</a>
</Link>
to re-verify your email.
</p>
<style jsx scoped>{`
a {
font-weight: bold;
color: #ed8f1f;
margin: 0 5px;
}
`}</style>
</div>
);

Related

Reusing next/font globally in nextjs 13

I'm migrating a create-react-app to nextjs and am learning the ups and downs for the first time. Nextjs 13 introduces next/font and it seems, as I'm learning nextjs for the first time, a good idea to use it in my workflow rather than learning methods that be deprecated.
Desire
I want to use several Google Fonts and be able to reuse them across the app dynamically. As in, I could create a single file:
fonts.js
import { Roboto, Poppins } from '#next/font/google';
export const roboto = Roboto({
weight: '400',
subsets: ['latin'],
variable: '--roboto-default'
});
export const poppins = Poppins({
weight: '400',
subsets: ['latin'],
variable: '--poppins-default'
});
And reference this in any component in such a way that if I change the const name, or any parameters, all affected components will change.
My previous experiences / familiarity
In react-create-app I used sass globals in external stylesheets. I could import google fonts the standard way (#import), in a stylesheet and create a variable like so:
globalfonts.sass
$font01: 'Roboto, arial, sans-serif';
Components throughout the app could have their own stylesheets that referenced:
import globalfonts.sass
.componentname {
font-family: $font01
}
And if I changed the value of $font01, all components would adjust. This made it very easy to sketch out changes. I could create a similar $font01--size variable too, etc.
Question
I'm looking for a similar functionality in nextjs13 using next/font as mentioned above in previous experiences, via a stylesheet.
I've created an app/fonts.js file and I import it in app/layout.js in the app directory but I'm a bit lost as to what to do next as documentation still seems to reference the older method of using the pages directory, which appears to be being phased out.
I can import a const from fonts.js into each component and reference them inline as constname.className. But this obfuscates things by splitting my styling between stylesheets and inline font references. If I want to change font configs across the entire app quickly, it feels so much more straightforward to use sass globals.
Follow up question:
As I feel like very few references to next/font online are mentioning stylesheets, I feel I need to ask: Are stylesheets dying out? Is styling each component inline on a component-by-component basis becoming more popular?
Attempt
If I try the following in app/layout.jsx
import { roboto, poppins } from './fonts';
import styles from './globals.scss'
export default function RootLayout({ children }) {
return (
<html lang="en">
{/*
<head /> will contain the components returned by the nearest parent
head.jsx. Find out more at https://beta.nextjs.org/docs/api-reference/file-conventions/head
*/}
<head />
<body className={roboto.className}>{children}</body>
</html>
)
}
The roboto font is not used. I'm unsure as to what I've done wrong.
And if I go and use className={roboto.className} on every single component I want to use this font for (some examples seem to suggest this method), it feels like I'm shooting myself in the foot if I want to change that font in the future. I'll have lost the single reference point I was using in my old method with having $font01

ZoomMtg is overwriting all css in my entire ReactJS website

Zoom websdk is used to integrate the zoom video platform into your application.
Here is the package for the same #zoomus/websdk.
All things are working fine for that video UI you've to import this CSS in your file. But the issue with this whole application is affected with this CSS and your styling is disturbed when you import this line to the main file.
import "#zoomus/websdk/dist/css/bootstrap.css"
import "#zoomus/websdk/dist/css/react-select.css"
Check out zoom forum for the same.
To resolve this I do a little twist in that
First you've to create a separate component that contains a code for zoomsdk like getting the signature and init the zoom all of that stuff.
Don't import those zoom related CSS to the parent file instead of that will go with another method.
Here is the step you need to follow
Copy those css file from node_modules to public folder.
Install react-helmet or react-helmet-async
In the same component write this line of code
<Helmet>
<link type="text/css" rel="stylesheet" href="/zoom-bootstrap.css" />
<link type="text/css" rel="stylesheet" href="/zoom-react-select.css" />
</Helmet>
One workaround can be to use React.lazy on its parent component.
I am using this temporarily until I find a complete solution to this.
import { ZoomMtg } from "#zoomus/websdk"; distors the ui for me. I am not importing the css. It does that automatically I think.

AEM 6.5: Is there an HTL way to output Webpack-generated CSS within <style> tags from an AEM clientlib category?

Goal:
I have a specific clientlib ready with "critical CSS" that I would like to add to a page template in <style> tags, per Google's performance recommendations on a high-traffic e-Commerce site.
Problem:
We all know how to add a file reference in HTL:
<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html" data-sly-call="${clientlib.css # categories='template.noncritical'}"/>
but how would I output plain generated CSS styles on the page via HTL? Is there some other HTL property I could use?
I want this:
<style>
/* contents of AEM clientlib CSS here */
</style>
Tried:
I have Googled, searched StackOverflow, and looked in the AEM docs about clientlibs, but haven't found anything about inlining styles, except to
use a third-party script to inline critical CSS. (don't want to do)
modify HTML Library Manager OSGi configuration to inline all styles by default (don't want to do)
I am looking for something AEM-native that can be turned "on" or "off" in HTL. Thanks for reading and offering any solutions you may have.
You can try https://github.com/dmantsevich/aem-critical-css
It will generate CSS files and "integrate" with AEM. You can use it for extract small component CSS.
Some features:
CSS will be loaded only, if component presents on the page
Supports 2 injection types: <style /> and <link />
Supports less, css, scss.
CSS will be injected only once
Example:
MyComponentTemplate.html
<sly data-sly-use.aemCriticalCSS="${'./_aem-critical-css.js'}"
#aem-critical-css="my-component/my-component.scss">${aemCriticalCSS.inject # context="unsafe"}</sly>
Where my-component/my-component.scss is a path to css (related to ui.frontend/src/ folder). We used it on several projects and it helps to improve rendering performance. (path can be configured)
You can use the Core Components functionality https://experienceleague.adobe.com/docs/experience-manager-core-components/using/developing/including-clientlibs.html?lang=en#inlining
<style type="text/css"
data-sly-use.clientlibs="${'com.adobe.cq.wcm.core.components.models.ClientLibraries' # categories='wknd.base'}">
${clientlibs.cssInline # context="unsafe"}
</style>

How to split css and load them only when needed on React+ReactRouter web app (built by WebPack)

I have a web app built by Web app, which takes a lot of time to first loading.
After investigation- I've tried a lot of improvements, also that one of using only critical CSS on server side rendering.
but now' after SSR has finished- React generates a lot more CSS rules- which are not used at this point,
so my question is:
Is that possible to split CSS and load them on demand (i.e.: on route change)?
Any help will be appreciated.
Thanks in advance!
Try using css-modules.
/* style.css */
.className {
color: green;
}
Let's say you have the above styles file. You can use the below code to apply the styles.
import styles from "./style.css";
const ExampleComponent = () => (
<div className={styles.className}>
Hello World!
</div>
);
You should do the webpack config to make importing CSS files to work.
css-modules documentation
Dynamically imported components / Async components react loadable.
I solved the problem by using the amazing package: 'react-universal-component',
you can read about it more here and here.
You can use then the css chunks, or the way I did it-
split css files according to your components, and call them from the component itself, without using a 'wholeCss.css' file or something like this.
This way, you can be sure that no needed css was not loaded.

Keeping CSS out of JS in Angular 2/Angular-CLI

By default, Angular 2 compiles the CSS into JavaScript, especially when using WebPack as in Angular-CLI. I would rather this not happen for a couple of reasons.
The first reason is that when I'm developing, I find it really helps to be able to see in the developer tools exactly what style sheet a specific style rule was coming from and what line number it was on. The second reason is that I think compiling CSS into the code kind of misses the point of good CSS, which is that you can apply a different style sheet and have an entirely different look and feel with the same markup.
Is there a flag somewhere that I can set to leave the CSS in .css files, where IMO it belongs?
This is the whole point of encapsulated components.
A component should have it's own styles encapsulated with it so it can be shipped with the styles.
Imagine you want to publish one of your components to be used by others, shouldn't it have its own styles with it ?
That means Angular needs a way to link those css to the component , thus seperates them into chunks and injects them into head tag.
To solve your problem though , you have couple of options :
1- Not using the Emulated Encapsulation :
Components by default have a property called encapsulation which is set to Emulated , you need to change it to None:
#Component({
encapsulation:ViewEncapsulation.None
})
Then , you can put all you css in the head tag your self like you'd do with a normal html page.
2- If the problem is theme ing , you can make your component themeable .
You can have a theme attribute for your component and then based on that change the styleing :
#Component({
selector:'my-component',
styles:[
`
:host{
[theme="blue"]{
change what ever you want :
h1{
color:blue;
}
}
}
`
]
})
And then , using this component would be like :
<my-component [attr.theme]='"blue"'></my-component> // would be blue theme
<my-component></my-component> // would be default
Go to your base Html file(where the root module, main app is injected) and link the CSS stylesheets in your header section.
Webpack will not include it in it's compiled/combined css file which is injected into the page. The css file will still be included at run time in the browser.
<html>
<head>
<base href="/">
<meta charset="utf-8">
<title>dummy</title>
<meta name="viewport" content="width=device-width">
//was not injected/modified by webpack
<link rel="apple-touch-icon" sizes="57x57" href="app/images/apple-icon-57x57.png">
//webpack's injected this below from other components's imported/inline css rules
<link href="index-c2cacb5fa3dfbca6116f4e4e63d5c3c7.css" rel="stylesheet"></head>
With angular-cli 1.6.5 you can do this:
ng serve --extract-css
You will still have the style-encapsulation features, but devtools will now point to the component css source file.
I use the angular-cli as well (v1.0.0-beta.22). When I am ready to build for production I run the following command:
ng build -prod -aot
This generates all my production-ready files (bundled, tree-shaken and minified etc). Of particular note is that it will generate two versions of the style sheets.
One in js:
styles.b2328beb0372c051d06d.bundle.js
And another version is plain css:
styles.4cec2bc5d44c66b4929ab2bb9c4d8efa.bundle.css
I run some post-processing on the css file with gulp and use the css version for my production build. I am not sure if the same holds true for lazy loading (where the cli will produced different chunks), but it works for sure when lazy loading is not being used (I haven't launched a production-ready project yet with lazy loading).
I also tried a build with JiT compilation:
ng build -prod
It also produced the raw/minified version of the css style sheet.
Now, I know for sure the folowing does NOT work:
ng build
This will produce all the css embedded within js file, styles.bundle.js.
Since you want to use the raw css file during development, the only workaround I can think of is that you run ng build -prod in order to get the css file. Copy/paste this manually into your assets folder. Run "format" on the file to un-minify the file. Then do a normal build with a modified index.html file referencing your raw css file, and removing the styles.bundle.js script reference. Not pretty, but it might work.
Put a wrapper class in html example-
<div class="component-1-wrapper">
all yout html here inside component-1-wrapper
</div>
Structure your sass(scss) in the following way. Since your styles are wrapped inside component-1-wrapper, therefore it will apply only to component-1-wrapperclass
.component-1-wrapper{
// all the styles for component-1 here
.class-hello{
// styles
}
}
You can compile your css with sass and put all the css(seperated by modules) in seperate folder.Start the filenames by _, sass can import them:
You can refer your styles-main.scss in app.ts file
#component({
styleUrls:['styles/styles-main.scss']})
The style-sheets will be structured this way and individual component's class styles will be applied to particular component since there is a wrapper class in html
Hope it helps!!!!!!

Resources