Knows Not Much
Knows Not Much

Reputation: 31526

Not able to import SVG image into my typescript application

I am trying to import an image (SVG) into my typescript application

import  * as logo from './images/logo';    
export default class App extends React.Component<{}, {}>{
    render() {
        return (
                <div className="App">
                    <header className="App-Header">
                        <img src={logo} className="App-logo" alt="logo" />
                        <h1 className="App-tite">Welcome to React</h1>
                    </header>
                </div>
        );
    }
}

but typescript still throws the error

ERROR in [at-loader] ./src/App.tsx:3:24 
    TS2307: Cannot find module './images/logo'.

I have a directory called images in the same location as App.tsx and it does have a logo.svg. In my webpack.config.js I also have a entry

resolve: {
  extensions: [".js", ".tsx", ".css", ".svg"]
}

I googled and found this thread https://github.com/microsoft/TypeScript-React-Starter/issues/12 But I don't know where to put globals.d.ts file (as recommended in the last post)

Also why is importing a simple image so hard?

Here is my repo

https://github.com/abhsrivastava/redux-tutorial

Upvotes: 1

Views: 4702

Answers (3)

Melisa M.
Melisa M.

Reputation: 121

If you are writing a typescript application, I suggest you use the microbundle package bundler make configurations easier. Microbundle is a “zero-configuration bundler for tiny modules".It’s a wrapper around rollup with sane defaults nice outputted size stats, multiple target formats (ES modules, CommonJS, UMD).

If you want to take a look https://github.com/developit/microbundle

--external flag to specify external dependencies

package.json

{  
  "name": "",
  "author": ",
  "version": "1.0.0",
  "description": "",
  "source": "src/index.tsx",
  "main": "dist/index.js",
  "exports": "./dist/index.modern.js",
  "unpkg": "dist/index.umd.js",
  "scripts": {
    "dev": "microbundle watch --external .*/font/.*,.*/style/.*",
    "build": "microbundle"
  },
  "devDependencies": {
    "microbundle": "^0.13.0"
  },
  "keywords": [],
  "license": "ISC"
}

Upvotes: 1

Thiago Camargo
Thiago Camargo

Reputation: 148

There is a couple of things, one of them is that your import is missing the extension, and by default it will try to look for a .ts file. Since you are importing the svg, you should do something like

import Logo from './images/logo.svg';

The other thing is, like you mentioned it yourself, you are missing a definitions file for that logo. You can either, next to logo.svg, create a logo.svg.d.ts or somewhere in your application create the globals.d.ts (it can be any name, any location)

Keep in mind that if you declare the module wrong, it will still not find it

The safest way is declare module '*.svg'; inside the global definitions file

Upvotes: 1

wentjun
wentjun

Reputation: 42516

One way of easily importing inline SVG files would be to make use of this package called svg-inline-react, which wraps your SVG into a component.

You can try installing it

npm i svg-inline-react

And on your component,

import InlineSVG from 'svg-inline-react';
import logo from './images/logo.svg';    

export default class App extends React.Component<{}, {}>{
  render() {
    return (
      <div className="App">
        <header className="App-Header">
          <div className="App-logo" /> 
            <InlineSVG src={logo} />
          </div>
          <h1 className="App-tite">Welcome to React</h1>
          </header>
      </div>
    );
  }
}

In addition, you might need to configure your webpack.config by adding an additional rule.

module.exports = {
  //...
  module: {
    rules: [
      //...
      {
        test: /\.svg$/,use: 'svg-inline-loader'
      }
    ]
  }
};

And then, you might need to declare the typings too.

interface SvgInlineReactProps {
  src: string;
  raw?: boolean;
  element?: string;
}

declare module 'svg-inline-react' {
  export default class InlineSVG extends React.Component<SvgInlineReactProps, any> {
  }
}

Upvotes: 1

Related Questions