gaoxiaoliangz / react-scoped-css

CSS encapsulation solution for React
456 stars 40 forks source link

Add docs for use with `customize-cra` #12

Open rohit-gohri opened 4 years ago

rohit-gohri commented 4 years ago

customize-cra is also a pretty popular cra config customizer. I am using antd and it is recommended in the docs.

If you could explain to me the logic in the craco plugin I might be able to get it to work with this also.

rohit-gohri commented 4 years ago

So I figured it out, mostly used the code from the craco plugin. Just used customize-cra helpers instead.

Maybe this can be moved into a small helper package too?

// config-overrides.js
const {
  override,
  getBabelLoader,
} = require('customize-cra');

/**
 * @see https://github.com/gaoxiaoliangz/react-scoped-css/blob/3888dd04c1/packages/craco-plugin-scoped-css/index.js
 */
function addScopedCSS(webpackConfig, env) {
  const addScopedCssLoader = (targetRule) => {
    const rules = targetRule.use || targetRule.loader;

    let cssLoaderIndex = -1;
    for (let i = 0; i < rules.length; i++) {
      const rule = rules[i];
      if (rule.loader && rule.loader.includes('css-loader')) {
        cssLoaderIndex = i;
        break;
      }
    }

    if (cssLoaderIndex !== -1) {
      const scopedCssRule = { loader: require.resolve('scoped-css-loader') };
      rules.splice(cssLoaderIndex + 1, 0, scopedCssRule);
    }
    else {
      console.log('no css-loader found');
    }
  };

  // add babel-plugin-react-scoped-css
  const loader = getBabelLoader(webpackConfig);
  loader.options.plugins.push(require.resolve('babel-plugin-react-scoped-css'));

  // add scoped-css-loader
  const oneOfRule = webpackConfig.module.rules.find((rule) => rule.oneOf);
  if (!oneOfRule) {
    return console.log(
      `Can't find a 'oneOf' rule under module.rules in the ${env} webpack config!`,
      'webpack+rules+oneOf',
    );
  }

  const cssRule = oneOfRule.oneOf.find(
    (rule) => rule.test &&
      rule.test.toString().includes('.css$') &&
      rule.test.toString().indexOf('.module') === -1,
  );
  if (!cssRule) {
    console.log(
      `Can't find the webpack rule to match css files in the ${env} webpack config!`,
    );
  }
  else {
    addScopedCssLoader(cssRule);
  }

  const sassRule = oneOfRule.oneOf.find(
    (rule) => rule.test &&
      rule.test.toString().includes('scss|sass') &&
      rule.test.toString().indexOf('.module') === -1,
  );
  if (!sassRule) {
    console.log(
      `Can't find the webpack rule to match scss/sass files in the ${env} webpack config!`,
    );
  }
  else {
    addScopedCssLoader(sassRule);
  }

  return webpackConfig;
}

module.exports = override(
  addScopedCSS,
);
gaoxiaoliangz commented 4 years ago

Thanks for the feedback, I'll add support for it when I have time.

millievn commented 4 years ago

@rohit-gohri @gaoxiaoliangz i also bother with the struggle. Thanks for your jobs.

565784135 commented 4 years ago

After the above operation: Cannot read property 'rules' of undefined

rohit-gohri commented 4 years ago

After the above operation: Cannot read property 'rules' of undefined

@565784135 Can you tell more about your environment? What version of 'react-scripts', 'react-app-rewired', 'customize-cra'? Have you setup customize-cra correctly?

565784135 commented 4 years ago
module.exports = {
  webpack:override(
   addScopedCSS,
    fixBabelImports('import', {libraryName: 'antd-mobile', style: true}),
    addLessLoader({
      javascriptEnabled: true,
      modifyVars: theme,
    })
  ),
  devServer: overrideDevServer(
    addScopedCSS,
    devServerConfig
  )

start 报错,build 无效。 配置: https://github.com/565784135/react-demo

放弃了,使用namespaces空间命名解决

rohit-gohri commented 4 years ago

@565784135

  devServer: overrideDevServer(
    addScopedCSS,
    devServerConfig
  )

You need to remove this from the "devServer" override. This is only for the webpack config, the "devServer" conf is a separate.

This is what it needs to look like:

module.exports = {
  webpack:override(
   addScopedCSS,
    fixBabelImports('import', {libraryName: 'antd-mobile', style: true}),
    addLessLoader({
      javascriptEnabled: true,
      modifyVars: theme,
    })
  ),
  devServer: overrideDevServer(
    devServerConfig
  ),
};
565784135 commented 4 years ago

@rohit-gohri Thank you for your answer. As a rookie, it is more expected that the development mode and production mode can be consistent.