boopathi / react-svg-loader

A loader for webpack, rollup, babel that loads svg as a React Component
MIT License
638 stars 85 forks source link

Failed to execute 'createElement' on 'Document': The tag name provided is not a valid name #197

Closed DonGiulio closed 5 years ago

DonGiulio commented 6 years ago

I'm trying to have react-svg-loader 2.1.0 to load SVG using webpack, but I'm getting this error:

Failed to execute 'createElement' on 'Document': The tag name provided ('/packs/bundles/Project/components/LogoPage/images/name-f15c8edd029d0f795dd71e3e39079866.svg') is not a valid name I configured everything vanilla from the docs:

//webpack config: 
module: {
    loaders: [
      {
        test: /\.svg$/,
        use: [
          {
            loader: "babel-loader"
          },
          {
            loader: "react-svg-loader",
            options: {
              jsx: true // true outputs JSX tags
            }
          }
        ]
      }
    ]
  }

the import statement in my react component:

import Logo from "./images/name.svg"; Not sure what other info might be relevant.

artem7902 commented 6 years ago

Hi i have same problem, this is a bug.

DonGiulio commented 6 years ago

FWIW I temporarily worked around it by including the source of my svg file inside a proper react component, it's been a bit tricky because I had to change quite some attributes, for example: font-size had to become fontSize and all the dash ones similarly.

here's my workaround code:

import React from "react";

const Logo = props =>
  <svg > 
.... svg code
  </svg>;

export default Logo;
isthisstackoverflow commented 6 years ago

+1

SharatRacha commented 6 years ago

Is this issue resolved? Any idea when it can be resolved or the root cause of the error?

painkkiller commented 6 years ago

Have the same issue

henrykuzmick commented 6 years ago

Same issue

SebaBoler commented 6 years ago

Have this same

iwarner commented 6 years ago

I have the same issue Possibly could be some SVGO configuration thats missing I see there is another package for this

https://github.com/boopathi/react-svg-loader/tree/master/packages/babel-plugin-react-svg

mritzman-dg commented 6 years ago

I'm running into the same issue. This is my setup, we published an npm package 'a' that contains svgs and uses 'react-svg-loader'. In my app's package.json I have package 'a' as a dependency. Whenever I use a component from package 'a' that imports and 'svg' I get this error within my app. Any ideas?

iwarner commented 6 years ago

I moved to SVGr - https://github.com/smooth-code/svgr

mritzman-dg commented 6 years ago

thanks for the suggestion but svgr has the same issue as react-svg-loader with the setup I mentioned above

JeandeCampredon commented 6 years ago

I hope it might help

But from your description your imported variable must be a string (since React is comparing with a tag name) Also I have got the very same issue when I tried to configure 2 different loaders (for inline svg and url svg) with a collision in the tests :

     ....
      {
        test: /\.(ttf|eot|svg)$/,
        use: 'file-loader?name=[name].[ext]',
      },
      {
        test: /\.inline.svg$/,
        use: 'svgr/webpack',
      },
     .....

I solved It with a simple exclusion

     ....
      {
        test: /\.(ttf|eot|svg)$/,
        use: 'file-loader?name=[name].[ext]',
        exclude: /\.inline.svg$/,
      },
      {
        test: /\.inline.svg$/,
        use: 'svgr/webpack',
      },
     .....
pedromagalhaes commented 6 years ago

I solved this issue using a Babel Plugin: https://www.npmjs.com/package/babel-plugin-inline-react-svg

Installation: yarn add babel-plugin-inline-react-svg --dev

Component import React from 'react'; import CloseSVG from './close.svg'; const MyComponent = () => <CloseSvg />;

Babel { "plugins": [ "inline-react-svg" ] }

jhnns commented 6 years ago

There is a bug in webpack which could be the cause for this: https://github.com/webpack/webpack/issues/7088

LeonhardPrintz commented 6 years ago

I have the same issue.

NawarYossef commented 6 years ago

Same issue here with a create react app project!

ghost commented 6 years ago

I had this same issue with an ejected create react app. The loader was only being run during in a dev environment and not the production. I had to add the below code right above file-loader in webpack.config.prod.js and it fixed my errors.

Webpack In webpack.config.prod.js

{
  test: /\.svg$/,
  use: [
    {
      loader: "babel-loader"
    },
    {
      loader: "react-svg-loader",
      options: {
        jsx: true // true outputs JSX tags
      }
    }
  ]
}

Component

import React from 'react';
import TwitterSVG from './twitter.svg';
const MyComponent = () => <TwitterSVG />;
yoni-wibbitz commented 6 years ago

Same issue, tried to add the webpack configuration and babel, still didnt work

MaximOrlovsky commented 6 years ago

@colincmcc working like a charm, thank you.

kwoncharles commented 6 years ago

I had this problem as well. But I figured it out. In my case, the problem is Dummy file. There was a non-extension file that has same name with JS file what I imported. I removed that Dummy file and it works!

juanlanus commented 5 years ago

Same as @knowncharles. I had a component in a file lacking the .js extension. After adding the extension no error any more.

luanleone commented 5 years ago

Hi I have the same issue and I fixed it changing my SVG file name From Checkmark.svg to checkmark.inline.svg don't know why but it works

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

unformatt commented 5 years ago

Make sure you don't have any other loader plugins trying to load/parse svg files like file-loader or url-loader.

ArturBaybulatov commented 4 years ago
import {ReactComponent as ArrowDownIcon} from '../assets/arrow-down.svg';

Importing like this worked for me.

The SVG is imported as a real react component, so can be used like this:

<ArrowDownIcon/>

Extra params are automatically accepted:

<ArrowDownIcon className="full-width" height={123}/>
andr1o commented 4 years ago

In my case removing width and height attributes from .svg file worked

mwood23 commented 4 years ago

I ran into this again after the upgrade to 6.0. In the source it appears they're including the svg extension in their file-loader path.

https://github.com/storybookjs/storybook/blob/7dc59dabc4621a587bed94e1ae780ae157d2246c/lib/core/src/server/preview/base-webpack.config.js#L69

I was able to fix it like this:

// main.js

module.exports = {
  webpackFinal: async (config) => {

    // Replaces the webpack rule that loads SVGs as static files to leave out SVG files for us to handle
    const indexOfRuleToRemove = config.module.rules.findIndex(rule => rule.test.toString().includes('svg'))
    config.module.rules.splice(indexOfRuleToRemove, 1, {
      test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/,
      loader: require.resolve('file-loader'),
      options: {
        name: 'static/media/[name].[hash:8].[ext]',
        esModule: false
      }
    })

    config.module.rules.push(
      {
        test: /.svg$/,
        use: ['@svgr/webpack'],
      },

    )
    return config
  },
}
jvnlwn commented 4 years ago

@ArturBaybulatov's solution did the trick.

Note that you have to use the import name ReactComponent exactly.

The ReactComponent import name is significant and tells Create React App that you want a React component that renders an SVG, rather than its filename.

See https://create-react-app.dev/docs/adding-images-fonts-and-files/#adding-svgs

CWSites commented 2 years ago

After trying ALL of the solutions above, @mwood23 has the winning one for me!

afdev82 commented 2 years ago

I have this issue too after switching from libsass to dart sass in a Ruby on Rails project. Since I can't think about any relation between the two packages, maybe there is some other loader injected, because my config stayed the same as before.

Make sure you don't have any other loader plugins trying to load/parse svg files like file-loader or url-loader.

How exactly I can check this? I have the following webpack configuration (using the shakapacker gem):

// See the shakacode/shakapacker README and docs directory for advice on customizing your webpackConfig.
const path = require('path');
const { webpackConfig, merge } = require('shakapacker')

webpackConfig.module.rules.forEach(rule => {
  if(rule.test.length) {
    rule.test = rule.test.filter(t => !t.test('.svg'));
  }

  if(!Array.isArray(rule.exclude) && rule.exclude.test('node_modules')) {
    rule.include = [
      rule.include,
      path.resolve(__dirname, '../../node_modules/react-visibility-sensor/visibility-sensor.js')
    ];
    rule.exclude = /node_modules\/(?!(react-visibility-sensor)\/).*/;
  }
});

const customConfig = {
  module: {
    rules: [
      {
        test: /\.svg$/,
        use: [
          'babel-loader',
          {
            loader: 'react-svg-loader',
            options: {
              jsx: true, // true outputs JSX tags
              svgo: {
                pretty: true,
                plugins: [
                  {
                    prefixIds: true
                  },
                  {
                    removeViewBox: false
                  }
                ]
              }
            }
          }
        ]
      }
    ]
  }
};

const mergedConfig = merge(webpackConfig, customConfig);

module.exports = mergedConfig;

Thank you for your support!

afdev82 commented 2 years ago

I solved the issue, in fact there was another loader for the svg. The shakapacker gem in the v6.2.0 has changed the way to specify the rules in the webpack configuration and this fragment didn't work anymore:

if(rule.test.length) {
    rule.test = rule.test.filter(t => !t.test('.svg'));
  }

To solve the issue, I removed the code from the forEach loop and after that

const svgRule = config.module.rules.find(rule => rule.test.test('.svg'));
if(svgRule) {
  svgRule.exclude = svgRule.exclude ? new RegExp(svgRule.exclude.source + /|\.svg$/.source) : /\.svg$/;
}

I write this if someone else will have the same issue.

AfroDevGirl commented 2 years ago

The issue for me was that an svg file was being used as a component, when it was imported as a string.

Before:

import SVGIcon from '../../../assets/images/icon.svg';

const MyComponent = () => {
  return (
    <SVGIcon />
  )
}

After:

import SVGIcon from '../../../assets/images/icon.svg';

const MyComponent = () => {
  return (
    <img src={SVGIcon} alt="icon" />
  )
}

Hopefully this helps anyone else who comes across this thread!

konrazem commented 1 year ago

@AfroDevGirl thank you so much it helped me a lot. I was using tsup (esbuild) to build React appliaction.

kodingKeiko commented 9 months ago

For anyone using GatsbyJs, I had the same problem and what worked for me was adding this configuration to the gatsby-config.js :

{
  resolve: 'gatsby-plugin-react-svg',
  options: {
    rule: {
      include: /\.inline\.svg$/ // <---- this line
    }
  }
} 

And import the SVG file like this:

import Icon from "../images/icon.inline.svg"

<Icon />
gavrilikhin-d commented 9 months ago

I ran into this again after the upgrade to 6.0. In the source it appears they're including the svg extension in their file-loader path.

https://github.com/storybookjs/storybook/blob/7dc59dabc4621a587bed94e1ae780ae157d2246c/lib/core/src/server/preview/base-webpack.config.js#L69

I was able to fix it like this:

// main.js

module.exports = {
  webpackFinal: async (config) => {

    // Replaces the webpack rule that loads SVGs as static files to leave out SVG files for us to handle
    const indexOfRuleToRemove = config.module.rules.findIndex(rule => rule.test.toString().includes('svg'))
    config.module.rules.splice(indexOfRuleToRemove, 1, {
      test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/,
      loader: require.resolve('file-loader'),
      options: {
        name: 'static/media/[name].[hash:8].[ext]',
        esModule: false
      }
    })

    config.module.rules.push(
      {
        test: /.svg$/,
        use: ['@svgr/webpack'],
      },

    )
    return config
  },
}

What is a main.js?

M23jJohn commented 4 months ago

Guys can you please help me a got the same Error saying like that it only appears when i go to My website help me 🥺