How to fix 'Cannot find module' in a vuejs module with npm link

18,925

I've created a CodeSandbox here

SvgIcon.vue

<template>
  <span v-html="icon"></span>
</template>
<script>
export default {
  name: "SvgIcon",
  props: {
    icon: {
      type: String,
      required: true
    }
  }
};
</script>


HelloWorld.vue

//Usage
<template>
  <svg-icon :icon="AlertIcon"></svg-icon>
</template>
<script>
import AlertIcon from "../assets/alert.svg";
import SvgIcon from "./SvgIcon";

export default {
  data() {
    return { AlertIcon };
  },
  components: {
    SvgIcon
  }
};
</script>

I've made some changes to your components.

  1. You need to import the image and pass it to your component because dynamic import causes complications when it comes to the absolute paths.
  2. I've removed some unnecessary fields from your SvgIcon code.

Hope this helps.

Share:
18,925
Aurélien Lemaitre
Author by

Aurélien Lemaitre

Updated on July 09, 2022

Comments

  • Aurélien Lemaitre
    Aurélien Lemaitre almost 2 years

    I've created a vuejs library with some components that could be used in many project. In that library, I've got a component which can load svg files to be used inline in html (svg-icon).

    It work great.

    But in this same library, I've got another component which use svg-icon with a svg image stored in the library.

    An import point, I'd like to use this library (node module) with an npm link

    Which is the good way to give the path of the svg image, or where to store it?

    I've tried a lot of different paths, but none of them is working...

    This is my svg-icon component:

    <template>
       <component :is="component"></component>
    </template>
    
    <script>
     export default {
       name: 'SvgIcon',
       props: {
         icon: {
           type: String,
           required: true
         }
       },
       data () {
         return {
           component: null
         }
       },
       watch: {
         icon: () => {
           this.load()
         }
       },
       computed: {
         loader () {
           return () => import(this.icon)
         }
       },
       methods: {
         load () {
           this.loader().then(() => {
             this.component = () => this.loader()
           })
         }
       },
       mounted () {
         this.load()
       }
     }
    </script>
    

    And this is the component which use svg-icon (the svg image is in the same folder actually) :

    <template>
       <svg-icon icon="~my-module/components/media/no-image.svg"></svg-icon>
       <svg-icon icon="./no-image.svg"></svg-icon>
    </template>
    <script>
    import SvgIcon from '../svg-icon/SvgIcon'
    
    export default {
      components: {
        SvgIcon
      }
    }
    </script>
    

    I always got this errors:

    Cannot find module '~my-module/components/media/no-image.svg'

    Cannot find module './no-image.svg'

    Which is the good path in that situation? Or should I put the svg file somewhere else? (I'd like to keep it in the library)

    • Seblor
      Seblor about 5 years
      import is a method which purpose is to import a JS-compatible module. SVG files are not modules. SVG file in icon prop => calls the icon watcher => calls the load method => fetches and instantly executes the function returned by the loader computed variable => calls import on the SVG file.
  • Aurélien Lemaitre
    Aurélien Lemaitre about 5 years
    It works in a standalone, but the problem is with an npm link to that library
  • Arthur
    Arthur almost 5 years
    @AurélienLemaitre: Check this out. It was a library of components I wrote about a year ago. It's not perfect, but I got the images working by inlining them into the element.