pradel / create-react-app-swc

Use swc in your create-react-app for faster compilation, development and tests
MIT License
129 stars 11 forks source link

SVG import not working #2

Closed kevinfaveri closed 2 years ago

kevinfaveri commented 3 years ago

Same as https://github.com/pradel/create-react-app-esbuild/issues/6, but for this plugin

Maybe CRA 4 uses SVGR babel plugin and since these plugins remove the babel-loader, it breaks things?

lpillonel commented 3 years ago

Facing the same issue while trying this plugin

kevinfaveri commented 3 years ago

I just took the SVGR babel plugin out of the question and created a NodeJS script to transform everything in a specified "/assets/svg" folder to a React Component.

If useful to anyone, the script works like that and is run on demand as I wish (the script ignores existing components):

const fs = require('fs');
const svgr = require('@svgr/core').default;
const template = require('./template');

async function transformSvgs() {
  const svgFiles = fs.readdirSync('./src/assets/svgs');
  for (let index = 0; index < svgFiles.length; index++) {
    const svgFile = svgFiles[index];

    const files = fs.readdirSync('./src/assets/svgs/components');
    if (!files.includes(svgFile.replace('.svg', '.js')) && svgFile !== 'components') {
      let svgCode = fs.readFileSync(`./src/assets/svgs/${svgFile}`).toString();
      const camelCasedComponentName = svgFile.replace('.svg', '').replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
      const capitalizedName = camelCasedComponentName.charAt(0).toUpperCase() + camelCasedComponentName.slice(1)
      const jsCode = await svgr(svgCode, {
        plugins: ['@svgr/plugin-svgo', '@svgr/plugin-jsx', '@svgr/plugin-prettier'],
        template,
      },
      { componentName: capitalizedName });
      fs.writeFileSync(`./src/assets/svgs/components/${svgFile.replace('.svg', '.js')}`, jsCode);
    }
  }
}

transformSvgs();
cktang88 commented 3 years ago

Seems like this is a cleaner solution https://github.com/pradel/create-react-app-esbuild/issues/6#issuecomment-876764980

phtrivier commented 2 years ago

What would be the clean way to fix this ? I understood the general strategy would be like this:

// craco.config.js
const CracoSwcPlugin = require('craco-swc');

module.exports = {
  plugins: [
      {
      plugin: CracoSwcPlugin
    },
  ],

  webpack: {
    configure: (webpackConfig) => {
      webpackConfig.module.rules.unshift({
        test: /\.svg$/,
        use: ['@svgr/webpack']
      });
      return webpackConfig;
    },
  }

};

As in :

(And ideally, this configuration would be done internally by the create-react-app-swc plugin, like it's done by the `create-react-app-esbuild" plugin, possibly hidden behind a flag)

However if I simply change the webpack config as done above, compiling any svg fails with:

TypeError: this.getOptions is not a function

I'm new to all this, so:

drefined commented 2 years ago

I hope this helps someone:

The this.getOptions is not a function error is related to the newer version of svgr, so pinning the version to 5.5.0 will fix that issue. For more information, refer to this issue: https://github.com/gregberge/svgr/issues/631

npm install --save-dev @svgr/webpack@5.5.0

My craco.config.js configuration:

const CracoSwcPlugin = require('craco-swc');

module.exports = {
    plugins: [
        {
            plugin: CracoSwcPlugin,
            options: {
                swcLoaderOptions: {
                    jsc: {
                        transform: {
                            react: {
                                runtime: 'automatic',
                            },
                        },
                    },
                },
            },
        },
    ],
    webpack: {
        configure: (webpackConfig) => {
            webpackConfig.module.rules.unshift({
                test: /\.svg$/,
                issuer: /\.[jt]sx?$/,
                use: ['@svgr/webpack'],
            });
            return webpackConfig;
        },
    }
};

The automatic react runtime is required if you don't import React from 'react' in your components.