react-app-rewired: css module with babel-plugin-import not work.

Hello,i used css module with babel-plugin-import,but it does’t work. either css module or babel-plugin-import work. here’s my config-overrides file:


const { injectBabelPlugin,getLoader } = require('react-app-rewired')
const rewireLess = require('react-app-rewire-less')
const cssLoaderMatcher = function(rule) {
    return rule.loader && rule.loader.indexOf(`css-loader`) != -1;
}
module.exports = function override(config, env) {
    let l = getLoader(config.module.rules,cssLoaderMatcher);

    l.options = {
        modules: true,
        importLoaders: 1,
        localIdentName: '[local]___[hash:base64:5]'
    }

    config = injectBabelPlugin(['import', { libraryName: 'antd', style: true }], config);
    config = rewireLess(config, env, {
        modifyVars: { "@primary-color": "#1DA57A" },
    })

    return config;
};

https://ant.design/docs/react/use-with-create-react-app i wanna use this React Ui library with css module , how should i do it

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 18 (1 by maintainers)

Most upvoted comments

@WhatAKitty i forked repo from @codebandits and put the code above in and tweaked it a bit:

https://github.com/andriijas/react-app-rewire-less-modules

I also added less options to less module loader which makes it possible to use theme variables in components (primary colors etc). Check example repo: https://github.com/andriijas/create-react-app-playground/

Check these files: Footer.less Footer.js theme.less config-overrides.js .env

Big thanks @WhatAKitty and @codebandits - saved me a lot of time

I changed it a little, the difference is that all css and less from node_modules , for example antd will load normally and all css and less loaded from src/ will be treated as css modules. No need for foo.module.less files.

Note the libraryDirectory: "es" in babel import for antd, will use node_modules/antd/es instead of node_modules/antd/lib

const path = require("path");

const { compose, getLoader, injectBabelPlugin } = require("react-app-rewired");

const rewireLessModules = (prefix = "", lessOptions = {}) => {
  const cloneDeep = require("lodash/clonedeep");

  const ruleChildren = loader =>
    loader.use ||
    loader.oneOf ||
    (Array.isArray(loader.loader) && loader.loader) ||
    [];

  const findIndexAndRules = (rulesSource, ruleMatcher) => {
    let result = undefined;
    const rules = Array.isArray(rulesSource)
      ? rulesSource
      : ruleChildren(rulesSource);
    rules.some(
      (rule, index) =>
        (result = ruleMatcher(rule)
          ? { index, rules }
          : findIndexAndRules(ruleChildren(rule), ruleMatcher)),
    );
    return result;
  };

  const findRule = (rulesSource, ruleMatcher) => {
    const { index, rules } = findIndexAndRules(rulesSource, ruleMatcher);
    return rules[index];
  };

  const cssRuleMatcher = rule =>
    rule.test && String(rule.test) === String(/\.css$/);

  const createLoaderMatcher = loader => rule =>
    rule.loader && rule.loader.indexOf(`/${loader}/`) !== -1;
  const cssLoaderMatcher = createLoaderMatcher("css-loader");
  const postcssLoaderMatcher = createLoaderMatcher("postcss-loader");
  const fileLoaderMatcher = createLoaderMatcher("file-loader");

  const addAfterRule = (rulesSource, ruleMatcher, value) => {
    const { index, rules } = findIndexAndRules(rulesSource, ruleMatcher);
    rules.splice(index + 1, 0, value);
  };

  const addBeforeRule = (rulesSource, ruleMatcher, value) => {
    const { index, rules } = findIndexAndRules(rulesSource, ruleMatcher);
    rules.splice(index, 0, value);
  };

   return function(config, env) {
    const cssRule = findRule(config.module.rules, cssRuleMatcher);
    cssRule.exclude = path.resolve(__dirname, "src");
    cssRule.include = path.resolve(__dirname, "node_modules");

    const lessRule = cloneDeep(cssRule);
    lessRule.test = /\.less$/;
    const cssModulesRule = cloneDeep(cssRule);

    cssModulesRule.include = path.resolve(__dirname, "src");
    cssModulesRule.exclude = path.resolve(__dirname, "node_modules");

    const cssModulesRuleCssLoader = findRule(cssModulesRule, cssLoaderMatcher);
    cssModulesRuleCssLoader.options = Object.assign(
      {
        modules: true,
        localIdentName: `${env === "production"
          ? prefix
          : "[local]"}-[hash:base64:8]`,
      },
      cssModulesRuleCssLoader.options,
    );
    addBeforeRule(config.module.rules, fileLoaderMatcher, cssModulesRule);

    addAfterRule(lessRule, postcssLoaderMatcher, {
      loader: require.resolve("less-loader"),
      options: lessOptions,
    });
    addBeforeRule(config.module.rules, fileLoaderMatcher, lessRule);

    const lessModulesRule = cloneDeep(cssModulesRule);
    lessModulesRule.test = lessRule.test;

    addAfterRule(
      lessModulesRule,
      postcssLoaderMatcher,
      require.resolve("less-loader"),
    );
    addBeforeRule(config.module.rules, fileLoaderMatcher, lessModulesRule);

    return config;
  };
};

module.exports = function override(config, env) {
  config = injectBabelPlugin(
    ["import", { libraryName: "antd", style: true, libraryDirectory: "es" }],
    config,
  );

  const rewires = compose(
    rewireHTML,
    rewireLessModules("my-css-prefix", {
      modifyVars: {
        "@primary-color": "#..",
        "@info-color": "#...",
        "@font-size-base": "14px",
      },
    }),
  );

  return rewires(config, env);
};

I’ve done something like this to get it working in my project

const { getLoader } = require('react-app-rewired');

const cssLoaderMatcher = function (rule) {
  return rule.loader && rule.loader.indexOf('css-loader') !== -1;
};

function rewireCSS(config, env) {
  const cssRules = getLoader(config.module.rules, rule => rule.test && String(rule.test) === String(/\.css$/));
  cssRules.test = /\.s?css$/;
  const cssLoader = getLoader(config.module.rules, cssLoaderMatcher);
  cssLoader.options = {
    modules: true,
    importLoaders: 1,
    localIdentName: '[local]___[hash:base64:5]',
  };
  return config;
}
module.exports = rewireCSS;

and

const { getLoader } = require('react-app-rewired');
const path = require('path');


function rewireLess(config, env, options = {}) {
  const lessExtension = /\.less$/;
  const fileLoader = getLoader(config.module.rules, rule => rule.loader && typeof rule.loader === 'string' && rule.loader.endsWith(`file-loader${path.sep}index.js`));
  fileLoader.exclude.push(lessExtension);

  const lessLoader = {
    test: /\.less$/,
    use: [
      'style-loader',
      'css-loader',
      {
        loader: 'less-loader',
        options,
      },
    ],
  };
  config.module.rules.push(lessLoader);
  return config;
}
module.exports = rewireLess;