jpkleemans / vite-svg-loader

Vite plugin to load SVG files as Vue components
MIT License
557 stars 59 forks source link

dynamically import not working when build #24

Closed zinken7 closed 1 year ago

zinken7 commented 2 years ago

@jpkleemans Hi, I used this but failed when build for production. It's working in dev mode

<script lang="ts">
  import { computed, defineComponent, defineAsyncComponent } from 'vue'
  export default defineComponent({
    props: {
      name: {
        type: String,
        default: undefined,
      },
    },
    setup(props) {
      const currentIcon = computed(() => defineAsyncComponent(() => import(`../../icons/${props.name}.svg?component`))).value
      return {
        currentIcon
      }
    }
  })
</script>
jpkleemans commented 2 years ago

Hi, thanks for reporting. Could you share an example project so I can reproduce the problem, and investigate how to resolve it.

zinken7 commented 2 years ago

I made an example here: https://github.com/zinken7/vite_svg_inline It only working on dev mode. It's not working when build. Live example: https://codesandbox.io/s/epic-williamson-sfmb5

jd-solanki commented 2 years ago

Hi @jpkleemans as I mentioned my another issue in https://github.com/jpkleemans/vite-svg-loader/issues/25#issuecomment-953545959 another thing I was trying to do is dynamically load SVG from a public directory(I ask for user input so I have to make it dynamic).

I write const Logo = () => import('../public/logo.svg'); I get error in console: Screenshot 2021-10-27 at 11 44 53 PM

but if I turn it in to import Logo from '../public/logo.svg'; it works fine.

However, using ../public/logo.svg still gives a warning: Screenshot 2021-10-27 at 11 46 45 PM

This is related to https://github.com/jpkleemans/vite-svg-loader/issues/25

If I turn url from ../public/logo.svg to /logo.svg I get error atttached in this comment https://github.com/jpkleemans/vite-svg-loader/issues/25#issuecomment-953545959

BTW I am using nuxt + TS if you are going to test it.

jpkleemans commented 2 years ago

@zinken7 does it work when omitting the ?component param?

silencerspirit commented 2 years ago

@jpkleemans

Hi! All imports on server-side (raw,url,component) calling error.

500 Cannot read properties of undefined (reading 'stubModule')

On client-side - its working;

Code example:

<template>
<component :is="icon" />
</template>

<script>
let icon = await import(`../../assets/svg/${props.name.toLowerCase()}.svg?component`).then((_) => _.default);
</script>
silencerspirit commented 2 years ago

@jpkleemans

Hi! All imports on server-side (raw,url,component) calling error.

500 Cannot read properties of undefined (reading 'stubModule')

On client-side - its working;

Code example:

<template>
<component :is="icon" />
</template>

<script>
let icon = await import(`../../assets/svg/${props.name.toLowerCase()}.svg?component`).then((_) => _.default);
</script>

Resolve this problem, create a functional component:

import { h } from 'vue';

const CommonIcon = (props, context) => {
 const svg = require(`../../assets/svg/${props.name}.svg`).default;
 return h('span', {...context.attrs, class: 'common-icon', }, [
    h(svg, { class: 'h-[inherit] w-[inherit]' }, [h(svg)]),
  ]);
}

CommonIcon.props = {
  name: {
    type: String,
    required: true,
  },
  width: {
    type: String,
    default: '',
  },
  height: {
    type: String,
    default: '',
  },
  size: {
    type: String,
    default: '',
  },
};

export default CommonIcon;
jpkleemans commented 2 years ago

@silencerspirit thanks for posting your solution!

cdwmhcc commented 2 years ago

import { h } from 'vue';

const CommonIcon = (props, context) => { const svg = require(../../assets/svg/${props.name}.svg).default; return h('span', {...context.attrs, class: 'common-icon', }, [ h(svg, { class: 'h-[inherit] w-[inherit]' }, [h(svg)]), ]); }

CommonIcon.props = { name: { type: String, required: true, }, width: { type: String, default: '', }, height: { type: String, default: '', }, size: { type: String, default: '', }, };

export default CommonIcon;

require is not defined

silencerspirit commented 2 years ago

@cdwmhcc you need install plugin vite-require;

In vite.config.ts:

import svgLoader from 'vite-svg-loader';
import { viteRequire } from 'vite-require';

export default {
  ...,
  plugins: [svgLoader(), viteRequire()]
};

and if you use vitest as test platform, in vitest.config.ts:

import { viteRequire } from 'vite-require';
import svgLoader from 'vite-svg-loader';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  ...,
  plugins: [vue(), viteRequire(), svgLoader()],
});
cdwmhcc commented 2 years ago

@cdwmhcc you need install plugin vite-require;

In vite.config.ts:

import svgLoader from 'vite-svg-loader';
import { viteRequire } from 'vite-require';

export default {
  ...,
  plugins: [svgLoader(), viteRequire()]
};

and if you use vitest as test platform, in vitest.config.ts:

import { viteRequire } from 'vite-require';
import svgLoader from 'vite-svg-loader';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  ...,
  plugins: [vue(), viteRequire(), svgLoader()],
});

Not working in nuxt.js 3

silencerspirit commented 2 years ago

@cdwmhcc you need install plugin vite-require; In vite.config.ts:

import svgLoader from 'vite-svg-loader';
import { viteRequire } from 'vite-require';

export default {
  ...,
  plugins: [svgLoader(), viteRequire()]
};

and if you use vitest as test platform, in vitest.config.ts:

import { viteRequire } from 'vite-require';
import svgLoader from 'vite-svg-loader';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  ...,
  plugins: [vue(), viteRequire(), svgLoader()],
});

Not working in nuxt.js 3

U welcome https://stackblitz.com/edit/github-1ck5ek?file=app.vue :)

cdwmhcc commented 2 years ago

I know the reason.

Cannot use defineComponent:

export default defineComponent({
    async setup(props, { emit, attrs, slots }) {
        return () => {
            return ()
        };
    },
});

Must use:

import { h } from 'vue';

const CommonIcon = (props, context) => {
 const svg = require(`../../assets/svg/${props.name}.svg`).default;
 return h('span', {...context.attrs, class: 'common-icon', }, [
    h(svg, [h(svg)]),
  ]);
}

CommonIcon.props = {
  name: {
    type: String,
    required: true,
  },
};

export default CommonIcon;
cdwmhcc commented 2 years ago

@silencerspirit Thank you for your reply. It will load all icons. I need to load on demand.