Managing SCSS themes with Webpack

Hi,

I’m using the latest Sage (beta 2) and I need to generate multiple CSS files according to themes. Each theme has its own SCSS file which defines variables, such as colors, and shares the rest of the styles with others. I’m defining a entry point in config.json for each one. When building files with yarn run build, each CSS is correctly generated. So far, so good.

The problem rises when developing with watch mode. Webpack seems to only consider the main SCSS file and I can’t figure out how to make it load one theme or another. I stumbled upon some Webpack plugins which relate to this need, such as:

but I don’t know how it could fit in Sage config. I’m kind of a newbie with Webpack and a bit lost :slight_smile:

A workaround seems to require the SCSS file in main.js, like require('../styles/theme/one.scss'), but it’s not really manageable because it would break the generated CSS when building files and I’d have to change it every time I test another theme.

Any idea?

Thanks!

Did you manage to get this working?

Yes, forgot to get back here, but here’s what I did.

  1. I duplicated main.scss: https://github.com/roots/sage/blob/master/resources/assets/styles/main.scss
  2. I added a new entry point here to this new file : https://github.com/roots/sage/blob/master/resources/assets/config.json
  3. I modified the script enqueue to load the right file: https://github.com/roots/sage/blob/master/app/setup.php#L14

The key would be to create a scss hierarchy that load common variables, then override some (like, colors), and finally load every other files. !default scss command could help.

It’s up to you to get the correct file according to the current theme. I’m using an Advanced Custom Field option page.

Hope it helps!

2 Likes

You got me puzzled. I’m trying to figure out the hierarchy and overrides. Do you have an example? I get the same problem over and over again. My build works like a charm. But my watch task keeps failing on the entry point.

Do you have any error message? The project is a bit old now and I can’t really get back to it now.

There are no errors. Maybe easier to explain my situation. I got a multisite. Site a and b. I want to different stylesheets for both sites but use the same theme. I created 2 entry points with different variables. When I build via “yarn run build” both my websites get the correct stylesheet. The problem is the watch task. For some reason Webpack/Sage isn’t looking at the entry points while watching so my variables are ignores. This is a problem while developing the theme.

Understood, I had the same scenario. Did you correctly duplicated this line?

Mine looks like this:

Note that it was done on Sage 9.0.0-beta.2 at that time.

"entry": {
    "main": [
      "./scripts/main.js",
      "./styles/main.scss"
    ],
    "a": [
      "./styles/a.scss"
    ],
    "b": [
      "./styles/b.scss"
    ],
    "customizer": [
      "./scripts/customizer.js"
    ]
  },

It looks like this.

Pretty weird. I usually do yarn run build to show errors (watch usually doesn’t output anything), but you said it compiles fine…

Is the watcher ignoring all your SCSS files, or only children files, or only entry files?

I don’t think the watcher is ignoring files. It detects changes and compiles. It’s just not loading the right css in the browser.

Oooooh right I totally forgot this one. I literally spent days on it… Please take a look at this thread: Yarn watch not generating styles directory

I had to bypass the way Webpack does HMR which doesn’t work when working with conditionally loaded CSS files.

Yes this is exactly what I’m talking about. But I still feel this should be a lot easier to accomplish from within Sage/Webpack.

Good luck to find any easier solution :slight_smile: The root issue is that Webpack isn’t building any CSS file when in watch mode, as HMR inserts styles from the RAM. It’s said to be more performant. Not sure if the issues it generates are worth it though… Maybe it is for 99% of use case, not for this particular one. Hope you’ll figure it out anyway!

Yes I think you are right. Thank you very much for explaining and helping. If I find something easier I will post it here.

1 Like

I think I got an easier way of dealing with this. I created an ACF option to select a theme per website. Theme A or B. I copied main.scss and main.js. and created 2 new entry points (theme-a and theme-b). I made sure to load both css and js file per website depending on the selected theme option. Now when I change the devUrl in config.json the watch task is loading/injecting the right css.

Downside: I have 2 separate js files. I will look into this next.

That’s pretty much how I handled it too. Not sure if having 2 JS entry points is the key that make it work… Would be weird!

The key is to load the right JS file per website/theme. I got only 1 JS per entry point.

Related? https://github.com/roots/sage/issues/1911