3

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?

Amen Ra
  • 2,843
  • 8
  • 47
  • 85

2 Answers2

2

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.

Amen Ra
  • 2,843
  • 8
  • 47
  • 85
0

I created my react app with CRA so for me it required adding a CRACO config that overrode the use of the MiniCssExtractPlugin whose optimization appears to be result in the inconsistent load order of the css during a production build

module.exports = {
  webpack: {
    configure: (webpackConfig, { env, paths }) => {
      // For whatever reason we can't find the loader MiniCssExtractPlugin.loader
      // but by looking up css-loader we can get access to the MiniCssExtractPlugin.loader and replace it with the one used in dev
      const { isFound, match: cssModuleRule } = getLoader(
        webpackConfig,
        loaderByName("css-loader"),
      );

      if (isFound) {
        cssModuleRule.parent.forEach((x) => {
          if (x.loader === MiniCssExtractPlugin.loader) {
            x.loader = require.resolve("style-loader");
          }
        });
      }
      return webpackConfig;
    },
  },
};