title: Create React Component Library using CRACO with Create React App
body: <p>I need to create a React Component Library, I want to use CRA as I want to refer to the code of the main application which is also written using CRA.</p>
  <p><strong>I tried babel</strong> but that only converts the JS code leaving all other files (CSS, SVG) as it is and the user of my library is not on CRA hence SVG support is not there.</p>
  <pre class="lang-js prettyprint-override"><code>// babel.config.js
  module.exports = function (api) {
      api.cache(true);
  
      const presets = [&quot;@babel/preset-env&quot;, &quot;@babel/preset-react&quot;];
      const plugins = [&quot;macros&quot;];
  
      return {
          presets,
          plugins,
      };
  };
  </code></pre>
  <pre class="lang-json prettyprint-override"><code>// package.json
  {
      &quot;scripts&quot;: {
          &quot;clean&quot;: &quot;rimraf dist/babel&quot;,
          &quot;build&quot;: &quot;npm run clean &amp;&amp; cross-env NODE_ENV=production babel src/lib --out-dir dist/babel --copy-files --ignore __tests__,spec.js,test.js&quot;,
      }
  }
  </code></pre>
  <hr />
  <p><strong>I tried parcel</strong> also but that is forcing me to <a href="https://parceljs.org/languages/svg/#importing-as-a-react-component" rel="nofollow noreferrer">change my syntax of including SVG</a>.</p>
  <pre class="lang-js prettyprint-override"><code>//.parcelrc
  {
      &quot;extends&quot;: &quot;@parcel/config-default&quot;,
      &quot;transformers&quot;: {
          &quot;*.svg&quot;: [
              &quot;...&quot;,
              &quot;@parcel/transformer-svg-react&quot;
          ]
      }
  }
  </code></pre>
  <hr />
  <p>So <strong>I tried CRACO</strong> also and used the below configurations but that is outputting JS and CSS separately and I am not able to merge them or auto-include when importing the component. I tried removing the <code>mini-css-extract-plugin</code> from loaders as well but not working.</p>
  <pre class="lang-js prettyprint-override"><code>//craco.config.js
  const path = require(&quot;path&quot;);
  const EsmWebpackPlugin = require(&quot;@purtuga/esm-webpack-plugin&quot;);
  
  module.exports = {
      webpack: {
          configure: (config, { paths }) =&gt; {
              //* Remove mini-css-extract-plugin from loaders
              // config?.module?.rules[1].oneOf.forEach((sett) =&gt; {
              //  if (sett.use) {
              //      sett.use = sett.use.filter((u) =&gt; {
              //          if (u.loader &amp;&amp; typeof u.loader === &quot;string&quot; &amp;&amp; u.loader.includes(&quot;mini-css-extract-plugin&quot;)) {
              //              return false;
              //          }
              //          return true;
              //      });
              //  }
              // });
  
              const isEsm = process.argv.includes(&quot;--esm&quot;) ? true : false;
              paths.appBuild = config.output.path = path.resolve(isEsm ? &quot;./dist/esm&quot; : &quot;./dist/cjs&quot;);
              // Set separate entry point when building the widget lib
              // https://webpack.js.org/concepts/entry-points
              config.entry = `${paths.appSrc}/lib/index.js`;
  
              // Output a &quot;window&quot; module and define its name via the library key.
              // This key will be what is referenced when the hub looks for
              // the correct module to dynamically load after the bundle is
              // injected into the DOM
              // https://webpack.js.org/configuration/output
              config.output.library = &quot;swimBookForm&quot;;
              config.output.libraryExport = isEsm ? undefined : &quot;default&quot;;
              config.output.libraryTarget = isEsm ? &quot;var&quot; : &quot;umd&quot;;
              config.output.filename = &quot;main.js&quot;;
  
              // Because this is being injected in the hub's index.html,
              // we don't need the HTML plugin
              config.plugins = config.plugins.filter(
                  (plugin) =&gt; plugin.constructor.name !== &quot;HtmlWebpackPlugin&quot;
                  // &amp;&amp; plugin.constructor.name !== &quot;MiniCssExtractPlugin&quot;
              );
  
              // If we're including custom CSS, make sure it's bundle easily identified
              const cssPluginIdx = config.plugins.map((p) =&gt; p.constructor.name).indexOf(&quot;MiniCssExtractPlugin&quot;);
  
              if (cssPluginIdx !== -1) {
                  config.plugins[cssPluginIdx].options.filename = &quot;../main.css&quot;;
              }
  
              // Exclude shared dependencies to reduce bundle size
              // https://webpack.js.org/configuration/externals
              config.externals = isEsm ? [] : [&quot;react&quot;];
  
              // Consolidate bundle instead of creating chunks
              delete config.optimization;
  
              return config;
          },
          plugins: {
              add: process.argv.includes(&quot;--esm&quot;) ? [new EsmWebpackPlugin()] : [],
              // remove: [&quot;MiniCssExtractPlugin&quot;],
          },
      },
  };
  </code></pre>
  <p><strong>package.json</strong></p>
  <pre class="lang-json prettyprint-override"><code>{
  ...
      &quot;scripts&quot;: {
          &quot;start&quot;: &quot;react-scripts start&quot;,
          &quot;build&quot;: &quot;craco build &amp;&amp; craco build --esm&quot;,
          &quot;test&quot;: &quot;craco test --env=jsdom&quot;,
          &quot;build:web&quot;: &quot;react-scripts build&quot;
      },
  ...
  }
  </code></pre>
  <hr />
  <p><strong>What changes should I make in CRA using CRACO to make it compatible with outputting React Component Library?</strong> I am sticking with CRA and want an extended solution to it because I want to use the features provided by it eg. a simple toolchain to maintain, out-of-the-box features like CSS modules, SVG components, etc. Also, having a CRA-based solution means it'll be (most probably) compatible with upcoming cool CRA features as well.</p>
  <hr />
  <p>For example we can take <a href="https://www.npmjs.com/package/@im-swim/swim-book-form" rel="nofollow noreferrer">this repo</a> as an example, I want to make this repo to be eligible to be used as per the given example.</p>