Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load different css files based on environment with NextJS

I'm building a frontend app using NextJS v.13 and this will be a generic frontend codebase that will be used by multiple sites.

I want to have:

  • button.site1.css
  • button.site2.css

And when I build the codebase for site1 I want to somehow tell the app to use button.site1.css when building.

Basically I want to achieve the following:

.env.local

HOST_NAME=site1

About.js

import styles from `./Button.${process.env.HOST_NAME}.scss`; // This doesn't work. "Imports must be string literals"

const About = () => {
    <div>
      <h1 className={styles.h1}">About Page</h1>
    </div>
  )
}
like image 517
Weblurk Avatar asked Aug 13 '26 06:08

Weblurk


2 Answers

Although @Felix Eklöf has recommended a very nice approach by programmatically renaming files. Here's something more simple, suitable, and convenient.

Just import both the styles in your component and depending on the variable from .env file use the one that is needed. Next.js automatically tree-shakes extra classes that are not used, so you don't have to worry about performance in production or making production have large CSS.

import styles1 from "your-styles1.module.scss";
import styles2 from "your-styles2.module.scss";

const styles = process.env.HOSTNAME === "host1" ? styles1 : styles2;

Much straightforward and easier to implement. Right?

Update

If you are looking for conditionally adding global styles. Use link inside next/head instead. First, put your styles inside public directory. Then, withing your _app.jsx

// do not import global styles that are scopped to specific HOST, 

export default function(...) {
    const styleSheetLink = getStyleSheetLink(process.env.HOSTNAME) // some logic to detect appropreate stylesheet.
...
    return (
        <>
            <Head>
                 <link href={styleSheetLink} .../>
            </Head>
            ...
        </>
    )
...
}

Update

To enable CSS Optimization, you need to install critters and enable CSS Optimization.

// next.config.js
...
   experimental: { optimizeCss: true }
...
}

And

yarn add critters
like image 70
mayank1513 Avatar answered Aug 16 '26 08:08

mayank1513


Here's one option, not sure if it will fit your problem entirely.

So, you have button.site1.css, button.site2.css etc.

  1. Add the env variable HOST_NAME=site1 as you suggested.

  2. Write a java/bash- script that copies either button.site1.css or button.site2.css based on HOST_NAME into a common name like just button.css.

  3. In your react components you import button.css instead.

import styles from `./button.css`;
  1. In package.json add that script in prebuild.
{
  "name": "npm-scripts-example",
  "version": "1.0.0",
  "description": "npm scripts example",
  "scripts": {
    "prebuild": "node copycss.js",
    "build": "next build",
  }
}
  1. You also have to copy any of the CSS files manually when you're editing so you don't get errors in the editors. Or just run the script you've written locally with env vars.

EDIT

I was unable to try it earlier, but here's and example of copy script. I tried it in a fresh next.js project and it worked.

./copy-css.js

const fs = require('fs')

const site = process.env.HOST_NAME

fs.copyFileSync(`./styles/button.${site}.css`, `./styles/button.css`)

I'm guessing you have more files than just button, then you could put all site-specific CSS files in a separate folder and search it in the copy-css.js script and run the copyFileSync on each file.

like image 34
Felix Eklöf Avatar answered Aug 16 '26 08:08

Felix Eklöf