6

I have the following structure in my project folder:

src
  |
   -> assets
     |
      -> general-icons
        |
         pointer-arrow.svg
  |
   -> components
     |
      -> lazy-loader
        |
         LazyLoader.tsx

LazyLoader is a functional react component in which i dynamically import a component, in this case, a svg file

import React from 'react';

export default function LazyLoader(path: string) {
  return React.lazy(() => import(path));
}

The 'path' propert is a string that contains the relative path to the svg file:

src/assets/general-icons/pointer-arrow.svg

And the pointer.svg is a normal svg:

<svg version="1.1" width="24" height="24" viewBox="0 0 24 24">
  <path d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z" />
</svg>

When i call the LazyLoader component passing the path as parameter, it gives an error as it couldn`t find the svg module:

Error: Cannot find module 'src/assets/general-icons/pointer-arrow.svg'

Anyone has any thoughts what´s going on?

Matheus Carvalho
  • 415
  • 7
  • 13

3 Answers3

2

Absolute import path don't work by default. Is your app bootstrapped with create-react-app? Create a jsconfig.json file at the root of your project:

{
  "compilerOptions": {
    "baseUrl": "src"
  },
  "include": ["src"]
}

Now you can import from assets/general-icons/pointer-arrow.svg anywhere in your app.

hotpink
  • 2,882
  • 1
  • 12
  • 15
0

You can import the images dynamically with the native js dynamic import('') there's no need for React Lazy. See a good example here: https://stackoverflow.com/a/70024111/7336232

However, you have to be aware of the path/content you pass to the import(path) because depending on how you are planning to include the images to import in the final bundle there could be restrictions. There are two main ways:

Note: This is for Rollup, in Webpack i didn't try it but should be similar

a)- Making rollup automatically include the possibles files to import while creating the bundle using the official plugin https://www.npmjs.com/package/@rollup/plugin-dynamic-import-vars please read the doc and notice how there are important restrictions in the 'path' string, essentially you should just set the file name in the variable, the rest of the path have to be fixed in the import('') in order to provide rollup a restricted scope to import. eg:

OK

import(../assets/img/${fileName}.svg)

Wrong

import(filePath)

b)- Include in the bundle programmatically the files you can dynamically import example

//rollup.config.js 
import copy from 'rollup-plugin-copy';

plugins: [
    copy({
        targets: [ { src: 'src/assets/icons/*', dest: 'lib/assets/icons' },],
    }),
           …        
],

With this option b) you have no restrictions on the variable content but have to be careful with what you included in the bundle.

Conclusion: You can use dynamic import(...) but if you not properly handle the files inclusion on the bundle, it can be possible they are excluded and then the dynamic import will fail in the consumer.

Juanma Menendez
  • 17,253
  • 7
  • 59
  • 56
-2

I'd put all the svgs in a function.

import React from "react";

export const Logo = (props) => (
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 27" {...props}>
    <path
      d="M112.2,9.6h-0.6v7....z"
    />
  </svg>
);

export const menu...

Then just import them as you need.

cjohndesign
  • 178
  • 6