0

I just ran npm run build on my vue 3 project and my vendor.js file turns out to be 10MB!!!

And when I briefly scan the code of that file, it seems to be mostly filled with svg code. So I'm assuming that that's all the icons from coreui. Because currently, my main.ts file has this code:

import { CIcon } from '@coreui/icons-vue'
import * as coreuiIcons from '@coreui/icons'
app.provide('icons', coreuiIcons)
app.component('CIcon', CIcon)

So I'm wondering if it's possible to let those icons load lazily, just whenever they're being called for in the templates.

So far, I've tried it like this:

// CIconWrapper.vue

<template>
  <CIcon :icon="i" :size="size" />
</template>

<script lang="ts" setup>
import { CIcon } from "@coreui/icons-vue"

const { icon, size = "" } = defineProps<{ icon: string, size?: string }>()
const i = await import('@coreui/icons')[icon]
</script>

And then as fas as a I know, asynchronous Vue components only really work when wrapping them inside a Suspense, so I created another wrapper for the wrapper:

// CIconWrapperSuspense.vue

<template>
  <Suspense>
     <template #default>
       <CIcon :icon="icon" :size="size" />
     </template>
     <template #fallback>
       Loading...
     </template>
  </Suspense>
</template>

<script lang="ts" setup>
import { Suspense } from "vue"
import { default as CIcon } from "./CIconWrapper.vue"

const { icon, size = "" } = defineProps<{ icon: string, size?: string }>()
</script>

And then I changed my code in main.ts to look like this:

import { default as CIcon } from '@/components/CIconWrapperSuspense.vue'
app.component('CIcon', CIcon)

But it doesn't do anything. Like literally nothing. No loading screen even.

So if you have any tips on how to make this actually work, I would be incredibly grateful. 🙏

1 Answer 1

0

Okay I fixed it! :-D

So I threw away CIconWrapperSuspense.vue, that wasn't necessary at all. Then I rewrote CIconWrapper.vue as follows:

<template>
  <CIcon v-if="i" :content="i" :size="size" :customClasses="customClasses" />
</template>

<script lang="ts" setup>
import { onMounted } from "vue"
import { CIcon } from "@coreui/icons-vue"

let i = $ref()
const { icon, size = "", customClasses = "" } = defineProps<{
  icon: string, size?: string, customClasses?: string|string[]|object
}>()

onMounted(async () => {
  const iconName = icon.replace(/-(\w)/g, match => match[1].toUpperCase())
  const fileName = icon.replace(/([a-z])([A-Z])/g, match => `${match[0]}-${match[1].toLowerCase()}`)
  // Vite / Rollup only accept dynamic imports that start with ./ or ../
  i = (await import(`../../node_modules/@coreui/icons/js/free/${fileName}.js`))[iconName]
})
</script>

And now my main.ts file has this code:

// icons
import CIcon from '@/components/CIconWrapper.vue'
app.component('CIcon', CIcon)
Sign up to request clarification or add additional context in comments.

Comments

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.