Combine CRA with Craco to effortlessly integrate and switch between various CSS themes

Directory structure:

src/index.tsx
src/themes/dark.scss
src/themes/light.scss
...

Customizing webpack with craco:

const path = require('path');

module.exports = {
  webpack: {
    configure: (webpackConfig, { env, paths }) => {
      webpackConfig.entry.push(
        path.join(process.cwd(), "src/themes/dark.scss"),
        path.join(process.cwd(), "src/themes/light.scss")
      );

      webpackConfig.module.rules.splice(1, 0, {
        test: /\.themes\/dark.scss$/,
        use: [
           { loader: require.resolve('sass-loader') },
           { loader: require.resolve('css-loader') }
        ]
      });

      webpackConfig.module.rules[3].oneOf[5].exclude = /\.(module|themes)\.(scss|sass)$/;
      webpackConfig.module.rules[3].oneOf[6].exclude = /\.themes\.(scss|sass)$/;
      webpackConfig.module.rules[3].oneOf[7].exclude.push(/\.themes\.(scss|sass)$/);

      return webpackConfig;
    }
  }
};

The purpose is clear - we aim to generate two theme-specific CSS files from the src/themes directory that can be manually switched by loading/unloading their <link> tags in the DOM. This approach was inspired by discussions on Stack Overflow and GitHub projects like Output 2 (or more) .css files with mini-css-extract-plugin in webpack and https://github.com/terence55/themes-switch/blob/master/src/index.js.

Now, let's address the challenges encountered after the build process:

Creating an optimized production build...
Compiled successfully.

File sizes after gzip:

  122.24 KB  build/static/css/2.2e93dcba.chunk.css
  762 B      build/static/js/runtime~main.a8a9905a.js
  191 B      build/static/css/main.d0c4fa77.chunk.css
  157 B      build/static/js/main.2063d3e0.chunk.js
  109 B      build/static/js/2.9b95e8c0.chunk.js

(The generic CSS files and some library files seem fine). However, there's no sign of the theme-specific CSS files. Attempts to resolve this issue using file-loader haven't been successful either.

Answer №1

To improve your webpack setup, my suggestion is to configure it in a way that all assets related to a specific theme are packed into a single chunk:

const themeFileRegex = /(\w+)\.theme\.(scss|sass)$/;

// Function that searches for a theme stylesheet in parent issuers
function getIssuerTheme(module) {
  const matches = themeFileRegex.exec(module.resource);
  if (matches) {
    return matches[1];
  } else {
    return module.issuer && getIssuerTheme(module.issuer);
  }
}

...

webpackConfig.optimization.splitChunks.cacheGroups = {
    ...webpackConfig.optimization.splitChunks.cacheGroups,
    themes: {
       test: getIssuerTheme,
       name: m => {
         const name = getIssuerTheme(m);
         return `theme.${name}`;
       },
       reuseExistingChunk: false,
     },
   };

By implementing this configuration, you will have chunks named theme.light, theme.dark, and so on.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Flexbox is not properly repeating elements horizontally

I am struggling to align text boxes horizontally within ngFor loop, and I can't seem to pinpoint the mistake. Here is the HTML code from the parent component: <div class="maintenance-section"> <div class="yearly"> ...

Utilizing JQuery to modify CSS in a partial view

My layout includes a button and a dynamically filled div below it using ajax and a partial view. Here is the code related to the button: $(document).on('click', '.btn-release', function () { StartReleaseVersionEdit(); ReleaseV ...

IE11 displaying errors with flex-box layout in Angular8 causing screen misalignment

I'm currently experiencing a CSS issue specifically in IE11, as it seems to work fine on all other browsers except for this one. The problem arises due to the length of a string causing the screen not to fit properly within the browser window. To add ...

Bootstrap 5.3 does not allow custom background colors to take precedence

Ever since the update to Bootstrap 5.3.1, I've been facing an issue where two custom background colors are not overriding the colors set by Bootstrap, even when using !important. Strangely enough, they were working fine before the update. Here are my ...

2 column setup in the last row of a CSS grid

Can anyone help me troubleshoot an issue with aligning two buttons to the right in a form using CSS grid? I've attached a screenshot for reference. https://i.stack.imgur.com/DFGrx.png **css ** .wrapper { width:75%; padding-top: 15px; padd ...

The resolution of custom Vue modules appears to be malfunctioning

UPDATE Good news - I have successfully resolved the problem and provided the solution below. Question I started a new project in Vue using the command: vue create hello-world with all the default options selected. Subsequently, I created an index.ts fi ...

Achieving dynamic height in a parent div with a sticky header using mui-datatables

Here are the settings I've configured for my mui-datatables: const options = { responsive: "standard", pagination: false, tableBodyHeight: '80vh', }; return ( <MUIDataTable title={"ACME Employee ...

Incorporate a text input feature into the Pikaday modal dialogue box

I'm currently in the process of revamping Pikaday and want to swap out the year select for a text input. However, every time I add an input field, it ends up being unresponsive. Despite not being disabled, z-indexed to the background, or having any op ...

Different Styles of CSS Borders for List Items

Hey, I'm facing an issue with using borders in list items. I wanted to add borders to all the elements in the <li>, but when the width of the <li> exceeds the window's width, the right side border disappears. How can I resolve this ...

Connecting click events to multiple items, without the need for multiple functions

I'm struggling with the efficiency of my Javascript and I believe there must be a better way to achieve my goal. To demonstrate my issue, I've created a simplified version of my project on JSFiddle. JSFiddle The main objective is to display inf ...

Encountering a npm script error while running on a Windows operating

While using webpack to build my application, I encountered the following error message in the command prompt: [email protected] dev D:\Myprograms\java script\forkify webpack --mode development The error mentioned: Insufficient num ...

Showing Stationary Pictures at Full Size in OpenLayers

I am trying to showcase static images as maps using a StaticImage layer in ol3, with the image size set at 100% in pixels. However, I am facing difficulty in ensuring that the displayed images are always the correct size based on the extent and zoom variab ...

Using jQuery to enable scrolling and dynamically changing classes

I'm currently working on enhancing my website with a feature that changes the opacity of the first section to 0.4 when a user scrolls more than 400 pixels down the page. I attempted the following code without success: if($("html, body").offset().top ...

Is there a way to incorporate background images into the <option> tags within a <select> dropdown menu?

Not sure if browsers support this feature. It works fine in a div, but that's not very semantically correct. Here is a rough mockup of what I'm trying to achieve: Mockup Link /* CSS for select elements on page */ select { position: relative ...

Text that fades in and out based on scrolling past a specific point

There's a text containing <p> and <h1>. The text finishes with one <h1>. I'm looking to speed up the Y translation of the <p> twice when I reach the bottom of the document (where the last h1 is located in the middle of th ...

Accordion-style animation in JavaFX

I attempted to add some styling to an accordion panel and encountered a issue. Unfortunately, my attempt was unsuccessful. accordion.setEffect(new DropShadow(BlurType.ONE_PASS_BOX, Color.BLACK, 8, 0, 2, 0)); The CSS approach I tried also did not yield t ...

Hover effect not activating on image within modal

only img:hover is working, but after adding this to the CSS: #user-profile #user-myModal .modal-body img:hover #user-profile #user-myModal .modal-body .change-pic i{ display: block; } it's not working. I changed the class and id names, tried eve ...

Fill your background with a stunning background image

I have encountered a common issue where the existing solutions do not seem to solve my problem. The background image I am working with is taller than it is wide, and I want its height to be 100% of the body's height. To achieve this, I attempted the f ...

Determine a comparative measurement using specific numerical values

I am currently in the process of creating a webpage and I want to ensure that it is responsive by adjusting certain values based on the width of the viewport. Specifically, I have a DIV element that I want to split into 2 columns. For smaller screens (min ...

Align the radio button group in the center with corresponding labels

I have several radio buttons with labels that vary in length. I am trying to figure out how to center them horizontally so that the labels are centered on the page, but still appear as if they are left-aligned. Desired result: Current HTML snippet: < ...