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

Aurélien Lemaitre picture Aurélien Lemaitre · Apr 25, 2019 · Viewed 15.3k times · Source

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)

Answer

Arthur picture Arthur · Apr 25, 2019

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.