Importing a CSS File from an Environment Variable in Next.js v14
Answered
Hashim posted this in #help-forum
HashimOP
I'm using Next.js v14 and need to import a CSS file from a URL stored in an environment variable. Since environment variables cannot be directly used in static import statements, I'm looking for the best approach to dynamically load the stylesheet while ensuring it applies globally. I want to follow Next.js best practices and avoid any performance or hydration issues. What is the recommended way to achieve this?
Answered by Losti!
You can apply the link to the CSS file and also the preload if you see necessary, both are fine, well if everything is solved I'm glad to have helped! ((remember to mark the solution;3)
42 Replies
HashimOP
and is that good?
^ in layout.tsx
<head>
<link
rel="stylesheet"
href={`${process.env.NEXT_PUBLIC_CDN_URL}/media/static/css/main.css`}
/>
</head>
^ in layout.tsx
@Hashim
@Losti! Try with this: https://nextjs.org/docs/app/api-reference/functions/generate-metadata#resource-hints.
HashimOP
Thanks for the suggestion! Could you provide a code example of how to implement this?
Give me a minute
@Losti! Give me a minute
HashimOP
Alright, no rush. Thanks!
@Hashim
huozhi's comment has an example that will help you with your case.
@Losti! huozhi's comment has an example that will help you with your case.
HashimOP
So, I need to use this code in a client component right?
@Losti! The documentation addresses that question! You should use the "use client" directive.
HashimOP
my url is
and I try to use ReactDOM.preload
And didn't work
I used it in the page.tsx
Client console:
${process.env.NEXT_PUBLIC_CDN_URL}/media/static/css/colors.css
and I try to use ReactDOM.preload
And didn't work
I used it in the page.tsx
Client console:
The resource http://localhost:3003/media/static/css/colors.css was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally
ReactDOM.preload(
`${process.env.NEXT_PUBLIC_CDN_URL}/media/static/css/colors.css`,
{ as: "style" }
@Hashim ts
ReactDOM.preload(
`${process.env.NEXT_PUBLIC_CDN_URL}/media/static/css/colors.css`,
{ as: "style" }
You need to specify it as a MIME Type, I assume you understood.
ReactDOM.preload(
'/https://cdn.com/bootstrap.min.css',
{ as: 'stylesheet' },
)
@Hashim Click to see attachment
HashimOP
If we can use stylesheet in the ReactDOM why the docs didn't tell us to use it instead of saying "import stylesheets directly in the layout"
hmm Let me try it myself, I will make a project to test this feature.
this example works:
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
{/* with link tag in root layout */}
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/Buttons/2.0.0/css/buttons.min.css"
integrity="sha512-x8eU2Yx8Pd8XjWOTv+S/2jXGe586o6Ow722EaqGwG+4hkWaW1ZSAIMYUAY5QDyMglc9fPT0E1kZRIBwsdggtqg=="
precedence="default"
crossOrigin="anonymous"
referrerPolicy="no-referrer"
/>
{/* It is important to set precedence="default" or the next js will not allow it. */}
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
</body>
</html>
);
}
Let's try the next one with ReactDOM.preload
@Losti! this example works:
tsx
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
{/* with link tag in root layout */}
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/Buttons/2.0.0/css/buttons.min.css"
integrity="sha512-x8eU2Yx8Pd8XjWOTv+S/2jXGe586o6Ow722EaqGwG+4hkWaW1ZSAIMYUAY5QDyMglc9fPT0E1kZRIBwsdggtqg=="
precedence="default"
crossOrigin="anonymous"
referrerPolicy="no-referrer"
/>
{/* It is important to set precedence="default" or the next js will not allow it. */}
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
</body>
</html>
);
}
HashimOP
the old one I was using and Its working
https://nextjs-forum.com/post/1349251749302501547#message-1349254162600300555
https://nextjs-forum.com/post/1349251749302501547#message-1349254162600300555
@Hashim the old one I was using and Its working
https://discord.com/channels/752553802359505017/1349251749302501547/1349254162600300555
Oh, I accidentally omitted it. If it works, you can leave it. Let me test if ReactDOM.preload works as expected and implement it if you're happy with it.
In my case, by not adding precedence="default" I got an error nextjs
I guess this error has not occurred to you so it must be an issue with a more recent version.
@Losti! You need to specify it as a MIME Type, I assume you understood.
tsx
ReactDOM.preload(
'/https://cdn.com/bootstrap.min.css',
{ as: 'stylesheet' },
)
*My bad, it's typed, so the mime type is not necessary.
@Losti! this example works:
tsx
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
{/* with link tag in root layout */}
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/Buttons/2.0.0/css/buttons.min.css"
integrity="sha512-x8eU2Yx8Pd8XjWOTv+S/2jXGe586o6Ow722EaqGwG+4hkWaW1ZSAIMYUAY5QDyMglc9fPT0E1kZRIBwsdggtqg=="
precedence="default"
crossOrigin="anonymous"
referrerPolicy="no-referrer"
/>
{/* It is important to set precedence="default" or the next js will not allow it. */}
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
</body>
</html>
);
}
HashimOP
So, if this works thats good
thank you
Works as expected for me
"use client";
import Image from "next/image";
import { preload } from "react-dom";
export default function Home() {
preload(
"https://cdnjs.cloudflare.com/ajax/libs/Buttons/2.0.0/css/buttons.min.css",
{ as: "style" }
);
return (
...page component
)
}
@Losti! Works as expected for me
tsx
"use client";
import Image from "next/image";
import { preload } from "react-dom";
export default function Home() {
preload(
"https://cdnjs.cloudflare.com/ajax/libs/Buttons/2.0.0/css/buttons.min.css",
{ as: "style" }
);
return (
...page component
)
}
In this case, it doesn't throw any errors because the other properties are not configured: integrity, precedence, crossOrigin, and referrerPolicy.
But you can add them if you need them.
But you can add them if you need them.
@Hashim thank you
Just check carefully in the devtools (network part) to see if it downloads correctly without any problems.;3
@Losti! Just check carefully in the devtools (network part) to see if it downloads correctly without any problems.;3
HashimOP
I saw it and its there and got
200 OK
but it didn't show up in the head tag and didn't get the colorsbeacuse I need the rel to be
stylesheet
not preload
when I changed the rel to
stylesheet
in the dev tools I got the colors@Hashim I saw it and its there and got `200 OK` but it didn't show up in the head tag and didn't get the colors
HashimOP
mb there It shows up in the head but as
rel="preload"
when I changed it to rel="stylesheet"
everything works fine@Losti! Works as expected for me
tsx
"use client";
import Image from "next/image";
import { preload } from "react-dom";
export default function Home() {
preload(
"https://cdnjs.cloudflare.com/ajax/libs/Buttons/2.0.0/css/buttons.min.css",
{ as: "style" }
);
return (
...page component
)
}
HashimOP
try to use any class of the buttons and tell me if its works
Okay, I was right. You have to use both. Preloading causes the browser to download the resource in advance for later use, but it doesn't automatically apply it to the document. So, by using a link in the root layout with a stylesheet, as I showed you at the beginning, you would already be preloading the CSS and applying it with <link rel="stylesheet"/> atributte.
@Losti! Okay, I was right. You have to use both. Preloading causes the browser to download the resource in advance for later use, but it doesn't automatically apply it to the document. So, by using a link in the root layout with a stylesheet, as I showed you at the beginning, you would already be preloading the CSS and applying it with <link rel="stylesheet"/> atributte.
HashimOP
so I use it both
the preload and the layout
ye
You can apply the link to the CSS file and also the preload if you see necessary, both are fine, well if everything is solved I'm glad to have helped! ((remember to mark the solution;3)
Answer