Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not work on nuxt 3 #86

Open
dacoto97 opened this issue Oct 14, 2021 · 16 comments
Open

Not work on nuxt 3 #86

dacoto97 opened this issue Oct 14, 2021 · 16 comments
Labels

Comments

@dacoto97
Copy link

image

@manuelodelain
Copy link
Collaborator

Thanks @dacoto97 for reporting this.
We have to support Vite.
Maybe we should use packages like https://github.com/visualfanatic/vite-svg or https://github.com/jpkleemans/vite-svg-loader
Related to:

@dacoto97
Copy link
Author

Solution:

npm install vite-svg-loader --save-dev
import { defineNuxtConfig } from "nuxt3"
import svgLoader from "vite-svg-loader"

export default defineNuxtConfig({
  vite: {
    plugins: [svgLoader()]
  }
})

@manuelodelain
Copy link
Collaborator

I reopen the issue because we need to add the support for Vite to this module

@niklasfjeldberg
Copy link

@manuelodelain anything new on this?

@manuelodelain
Copy link
Collaborator

Hi @niklasfjeldberg Unfortunately not ! I would like to do something really soon but had no time to check Vite / Nuxt3. Any help would be appreciated.

@stuible
Copy link

stuible commented Oct 13, 2022

@dacoto97

This solution appears to break Nuxt 3's asset resolution
eg <img src="~/assets/icons/icon.svg" />

Have you found a workaround for this ?

@digitalcortex
Copy link

digitalcortex commented Nov 29, 2022

Solution:

npm install vite-svg-loader --save-dev
import { defineNuxtConfig } from "nuxt3"
import svgLoader from "vite-svg-loader"

export default defineNuxtConfig({
  vite: {
    plugins: [svgLoader()]
  }
})

I appreciate you sharing this! However the problem with this solution is that vite-svg-loader does not work with "~" paths, meaning you need to rewrite all your SVG paths to "../assets/icon.svg" pattern. Sounds a bit limiting when you want to keep using location-independent paths in your project

@johannschopplich
Copy link

In Nuxt 3, you don't need vite-svg-loader, but can instead create a custom component utilizing Vite's glob import:

<template>
  <span v-if="icon" class="h-[1em] w-[1em]" v-html="icon" />
</template>

<script setup lang="ts">
const props = defineProps<{
  name?: string
}>()

// Auto-load icons
const icons = Object.fromEntries(
  Object.entries(import.meta.glob('~/assets/images/*.svg', { as: 'raw' })).map(
    ([key, value]) => {
      const filename = key.split('/').pop()!.split('.').shift()
      return [filename, value]
    },
  ),
)

// Lazily load the icon
const icon = props.name && (await icons?.[props.name]?.())
</script>

@digitalcortex
Copy link

digitalcortex commented Dec 9, 2022

In Nuxt 3, you don't need vite-svg-loader, but can instead create a custom component utilizing Vite's glob import:

<template>
  <span v-if="icon" class="h-[1em] w-[1em]" v-html="icon" />
</template>

<script setup lang="ts">
const props = defineProps<{
  name?: string
}>()

// Auto-load icons
const icons = Object.fromEntries(
  Object.entries(import.meta.glob('~/assets/images/*.svg', { as: 'raw' })).map(
    ([key, value]) => {
      const filename = key.split('/').pop()!.split('.').shift()
      return [filename, value]
    },
  ),
)

// Lazily load the icon
const icon = props.name && (await icons?.[props.name]?.())
</script>

I wish I knew that before... Although vite-svg-loader offers SVGO optimization, is there any way to use svgo with vite glob import?

@johannschopplich
Copy link

Nope, no SVGO for now. But I will create a module for that.

@BenjaminOddou
Copy link

In Nuxt 3, you don't need vite-svg-loader, but can instead create a custom component utilizing Vite's glob import:

<template>
  <span v-if="icon" class="h-[1em] w-[1em]" v-html="icon" />
</template>

<script setup lang="ts">
const props = defineProps<{
  name?: string
}>()

// Auto-load icons
const icons = Object.fromEntries(
  Object.entries(import.meta.glob('~/assets/images/*.svg', { as: 'raw' })).map(
    ([key, value]) => {
      const filename = key.split('/').pop()!.split('.').shift()
      return [filename, value]
    },
  ),
)

// Lazily load the icon
const icon = props.name && (await icons?.[props.name]?.())
</script>

Your solution is super interesting but I am still a bit confused. Is there a way to avoid the span in this situation and import svg as pure component ? I would like to pass some class to the svg itself and it's kind of annoying having this span wrapping it. Also using v-html can be dangerous in some situation and I would prefer avoiding it but I don't see another way to go with your solution.

@madc
Copy link
Contributor

madc commented Feb 9, 2023

@BenjaminOddou You should be able to get rid of the span by generating a VNode.

Something like (untested):

const VNode = () => h('svg', { innerHTML: /* your content */ })

@BenjaminOddou
Copy link

Hello @madc and thank you very much for your response. I finally succeeded to get rid of the span with vite-svg-loader by creating a "SVG component" :

<!-- TheSVG.vue -->
<script setup lang="ts">
const props = defineProps<{ name: string }>()
const icon = defineAsyncComponent(() => import(`../assets/svgs/${props.name}.svg?component`))
</script>

<template>
  <component :is="icon" />
</template>
<!-- SomePage.vue -->
<template>
      <TheSVG id="big-circle" name="big-circle" />
</template>

but I still struggle to interact with inline elements inside svg when they are imported. In a nutshell, I remarked that my inner svg elements aren't accessible onMounted (querySelector returns null after NuxtLink but working on hard reload).

I created a discussion about it here. Don't hesitate to leave a message or suggestion 😃

@sh770
Copy link

sh770 commented Feb 15, 2023

I defined these two lines in the main.js file

import logo from './public/vite.svg'
       <img src="${logo}" class="logo" alt="Vite logo" />

Then I ran npm run build

and the icon is displayed

@g-libardi
Copy link

I defined these two lines in the main.js file

import logo from './public/vite.svg'
       <img src="${logo}" class="logo" alt="Vite logo" />

Then I ran npm run build

and the icon is displayed

An alternative to this solution that does not throw an error:

// you can get the path or filename from props or whatever
const logo = "/_nuxt/public/logo.svg"
<img :src="`${logo}`" class="logo" alt="Vite logo" />

@moh1434
Copy link

moh1434 commented Nov 28, 2023

use vite-svg-loader
but don't foget to pass 'raw' as defaultImport

      svgLoader({
        defaultImport: 'raw',
      })

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests