4

I'm trying to convert my Vue2/Webpack app to Vue3/Vite.

In Vue2/Webpack, this works:

<div v-html="require('!!html-loader!../../assets/icons/' + this.icon + '.svg')"></div>

Html-loader is added with:

"html-loader": "1.3.2",

In Vue3/Vite this throws the error: ReferenceError: require is not defined

I've looked around for an example of doing this but don't see how to do this without knowing the name of the file at compile time. Is that possible?

3 Answers 3

5

You could also use Lazy Load Components technique with defineAsyncComponent from Vue3 - 🔗ref.

or import() like is shown by @tony19 in this answer:

<script>
const getServiceIcon = async iconName => {
  const module = await import(/* @vite-ignore */ `../assets/svg/${iconName}.svg`)
  return module.default.replace(/^\/@fs/, '')
}

export default {
  data() {
    return {
      icon: null,
      iconName: 'icon1', // icon1.svg
    }
  },
  watch: {
    iconName: {
      async handler(iconName) {
        this.icon = await getServiceIcon(iconName)
      },
      immediate: true,
    },
  },
}
</script>

<template>
  <button @click="iconName = 'icon2'">Change to another SVG</button>
  <img :src="icon" height="72" width="72" />
</template>
Sign up to request clarification or add additional context in comments.

1 Comment

This is perfect. I am on a quest to use as few third party plugins as possible, and use only svg. Used this to create a component to replace zondicons, just changig the watcher to mounted. (never liked the heroicon method of one component for each icon...). thx / mike
4

You can take a look at vite-svg-loader plugin, and load SVG files as Vue components.

Comments

4

Simply by creating a component where you will load the icons. Using composition API here.

<template>
    <i v-html="svg" />
</template>

<script lang="ts" setup>
    import { computed } from 'vue';

    const props = defineProps(['icon', 'src']);
    const path = props.src ? props.src : '';
    const file = `${path}icon-${props.icon}`;
    const modules = import.meta.glob('../../assets/icons/**/*.svg', { as: 'raw' });

    const svg = computed(() => {
        return modules['../../assets/icons/' + file + '.svg'];
    });
</script>

<style lang="scss" scoped></style>

This will allow you to even style your SVG using css, tailwind etc...

The usage:

<UiIcon icon="NAME" class="w-8 fill-current text-red-500"/>

Done.

1 Comment

Did you really use v-html?!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.