webpack 4: Create multiple theme css files
Asked Answered
G

2

7

I need to create multiple theme CSS files using webpack version 4 and "mini CSS extract plugin" in my react project. Depends on a place where webpack will find an import of the SCSS file, it should use loader twice - with different data in sass-loader options.

I found nothing useful in the Internet according this goal. I also have already tried to use such webpack's loaders as: webpack-combine-loaders, multi-loader etc...

here is a part of webpack config

module: {
  rules: [
    {
       test: /\.scss$/,
       use: [
         {
           loader: MiniCssExtractPlugin.loader,
         },
         'css-loader',
         {
            loader: "sass-loader",
            options: {
               data: '$theme: dark;',
            }
         },
       ],
     },
     { // the same except data in options
       test: /\.scss$/,
       use: [
         {
           loader: MiniCssExtractPlugin.loader,
         },
         'css-loader',
         {
            loader: "sass-loader",
            options: {
               data: '$theme: white;',
            }
         },
       ],
     },
  ],
},
plugins: [
  new MiniCssExtractPlugin({
    filename: 'client.white.css',
  }),
  new MiniCssExtractPlugin({ 
    filename: 'client.dark.css',
  }),
],

and in my scss file (button.scss) I use such condition:

$background: #06cc1a;
$color: white;

@if $theme == dark {
  $background: white;
  $color: black;
}

.button {
    background-color: $background;
    color: $color;
  }
}

as a result, I want to get two CSS files client.white.css where were applied sass variables for the white theme and client.dark.css where were applied variables for the dark theme

Gossipy answered 14/4, 2019 at 19:16 Comment(0)
G
4

We solved this in our project by using multiple entry points, one for each theme, e.g:

entry: {
    light: './src/css/light.scss',
    dark: './src/css/dark.scss'
}

With the contents of light.scss files being as follows:

$background: #001560;    

@import "~base/scss/base.scss";

Webpack will output a single css file for each theme containing all the styles, both base and theme-specific, which is great when optimising for production.

Note though that you will also get a redundant JS file, which you may want to clean up post-build.

Greatuncle answered 17/7, 2019 at 13:40 Comment(4)
this is one of the possible solutions, but situation with creating of a redundant js file is a bit annoying. In our project we had to write own webpack loader with plugin for solve this problemGossipy
indeed js files are annoyingAnte
@AvrelDusop do you have that loader on Github?Toast
@ItayGanor this question (and accepted answer) has an example: https://mcmap.net/q/1176247/-delete-or-not-create-a-file-for-each-entry-in-webpackGreatuncle
F
0

I worked on a web app which use multi theme, and we tackle the problem by saving each theme's colors to backend, so we can get the value from API depending from query, and for styling, we use styled-components for that.

I find css-in-js is really useful in this kind of problem. We actually use both styled components and LESS css for our styling. styled-components are used for coloring based on theme, and the rest is on LESS css. Perhaps you can try to use that too, or even a inline css should do the work since JS variable would work on that.

A specific example is to build a ThemeProvider component that engulf the whole application as its child, ThemeProvider will contain the declaration of class with the use of styled-components and that class can be reused throughout application scope.

Footstool answered 14/4, 2019 at 21:24 Comment(2)
Styled-components it's definitely not a good idea, it's a mess. Let's separate css and js components.Gossipy
I actually agree with you, I despise styled-components too, but it did the trick, so I stayed @AvrelDusopFootstool

© 2022 - 2024 — McMap. All rights reserved.