2

I have set up webpack to load SVG files into my TSX port of the create-react-app, per this answer:

const logo = require('./logo.svg');

However, when I try to use it as follows I get a nasty 404.

<img src={logo} className="App-logo" alt="logo" />
Failed to load resource: the server responded with a status of 404 ()        [object%20Module]:1 

This makes sense - I require the svg, so it loads as a module, and you can't jolly well make a src URL out of that.

That being said, how do I use an SVG loaded into a TSX file as a module via require? Is this possible? I am aware the above answer is outvoted by the more popular approach specified here, but I want to see if this option can work as well. Because what is programming if not a thousand ways to skin a cat? Or shoot yourself in the foot...

Bondolin
  • 2,793
  • 7
  • 34
  • 62

2 Answers2

0

If you're using require on a svg file, then the variable will be a string like <svg>...</svg>. In the case of simple html, you could just add that with string interpolation. Might work with JSX as well.

Judah Meek
  • 565
  • 7
  • 16
0

For some reason, the alternate type file for other extensions didn't seem to work for me. Instead, what I've found (with a fairly brand-spankin'-new CRA repo) was just change it to look roughly like the following:

const { default: logo } = require('./logo.svg') as { default: string };

It's not a great situation there, but you could potentially wrap requiring other assets by doing something like:

function requireAsset(src: string): { default: string } {
    return require(src);
}

The only drawback that I can see is that you'll get annoying warnings that I can't find a way to suppress. The reason for that is that it's a warning straight from webpack, so though it will say to try to use // eslint-disable-next-line, it will not work. If there are no other warnings or errors, then you should be fine with the assets specifically.

Update 1

Looking into an issue surrounding the warning I mentioned above, the reason for the warning might stem from the fact that webpack doesn't know how to resolve a dynamic asset like that, which might mean that it pulls in more than it should. If you need to suppress the warning further, it is possible by putting an interpolated string with the parameter in it, though I'd not be surprised if webpack would then detect when this is being done and result in the same warning. One of the suggestions from the maintainers is to add some specificity as to what file it might require, such as hard-coding a specific path. You could potentially add a folder such as assets with the logo in it and refactor the wrapper function to point to that folder:

function requireAsset(src: string): { default: string} {
    return require(`./assets/${src}`);
}

The above code would restrict the included assets to just the assets folder and any subdirectories.

The problem as I see it is that any of these workarounds aren't really that great because it might start to mess with the dependency resolution with webpack and that could be problematic. The better option (if it works) would be to have that assets.d.ts file that's included in the tsconfig.json and as mentioned in the related question.