Search code examples
reactjswebpacklesses6-module-loader

How to determine the order of css in my create react app build with webpack and customize-cra?


I am trying to change how to keep the same order of my css in development as I do in my build for my app using Create React App. When I am running my app in development mode the css loads like this:

<style>custom injected css 1</style>
<style>custom injected css 2</style>
<style>css that is a part of the chunk.css</style>

But my build looks like this

<style>css that is a part of the chunk.css</style>
<style>custom injected css 1</style>
<style>custom injected css 2</style>

Now I am using customize-cra to customize Create React App and here is what the config-overrides.js file looks like

const _ = require("lodash");
const path = require("path");
const {
  override,
  addDecoratorsLegacy,
  disableEsLint,
  addWebpackModuleRule,
  addWebpackAlias,
  useBabelRc,
} = require("customize-cra");

function addCustomLessModule(config, env) {
  const fileLoaderCustomExtension = /\.(jpe?g|gif|bmp|mp3|mp4|ogg|wav|eot|ttf|woff|woff2)$/;
  const configExtension = /\.(config|overrides|variables)$/;
  const fileLoader = _.find(
    config.module.rules[2].oneOf,
    (rule) => rule.loader && rule.loader.indexOf("file-loader") !== -1
  );
  const customFileLoader = _.cloneDeep(fileLoader);
  customFileLoader.test = fileLoaderCustomExtension;
  customFileLoader.use = ["file-loader"];
  delete customFileLoader.loader;
  delete customFileLoader.options;
  fileLoader.exclude = (fileLoader.exclude || []).concat([
    fileLoaderCustomExtension,
    configExtension,
  ]);
  config.module.rules[2].oneOf.push(customFileLoader);
  const lessExtension = /\.less$/;
  const lessLoaders = [{
      loader: "style-loader"
    },
    {
      loader: "css-loader"
    },
    {
      loader: "less-loader"
    },
  ];
  config.module.rules[2].oneOf.push({
    test: lessExtension,
    use: lessLoaders,
  });

  return config;
}

module.exports = override(
  addCustomLessModule,
  addDecoratorsLegacy(),
  addWebpackModuleRule({
    test: /\.less$/,
    use: [{
        loader: "style-loader"
      },
      {
        loader: "css-loader"
      },
      {
        loader: "less-loader"
      },
    ],
  }),
  addWebpackAlias({
    ["../../theme.config$"]: path.join(__dirname, "./src/styles/theme.config"),
  }),
  addWebpackAlias({
    ["../semantic-ui/site"]: path.join(__dirname, "./src/styles/site"),
  }),
  // disableEsLint(),
  useBabelRc()
);

The files ["../../theme.config$"]: path.join(__dirname, "./src/styles/theme.config"), and ["../semantic-ui/site"]: path.join(__dirname, "./src/styles/site") are <style>custom injected css 1</style> and <style>custom injected css 2</style>

What can I do to make them dynamically load before <style>css that is a part of the chunk.css</style> in my build?


Solution

  • So first I had to set an environmental variable in my package.json file for my start script when I am doing local developement "start": "NODE_ENV=Local react-app-rewired start",

    Then in my customizer-cra config-overrides.js I set my node environmental variable const isLocal = process.env.NODE_ENV === 'Local'; And then I imported the MiniCssExtractPlugin plugin from webpack const MiniCssExtractPlugin = require('mini-css-extract-plugin');

    Then I put a ternary to check if the app is running locally where this does not occur or if it is in production where it does occur. The style-loader was loading the chunk.css file before the compiled less code in this situation but it could have been sass also. so I change the code from this:

    addWebpackModuleRule({
        test: /\.less$/,
        use: [
          { loader: 'style-loader'},
          { loader: 'css-loader' },
          { loader: 'less-loader' }
        ],
      }),

    To this:

    addWebpackModuleRule({
        test: /\.less$/,
        use: [
          { loader: isLocal ? 'style-loader' : MiniCssExtractPlugin.loader },
          { loader: 'css-loader' },
          { loader: 'less-loader' }
        ],
      }),

    and that fixed the issue.