最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

vite - How to remove icon font files from Vuetify app? - Stack Overflow

programmeradmin1浏览0评论

This is my vite-config.js

import { fileURLToPath, URL } from 'node:url'

import { defineConfig, splitVendorChunkPlugin } from 'vite'
import vue from '@vitejs/plugin-vue'
import usePHP from 'vite-plugin-php'

export default defineConfig({
  plugins: [
    usePHP({
      binary: 'C:/tools/php83/php.exe',
    }),
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => ['v-list-item-content', 'v-list-item-group'].includes(tag),
        }
      }
    }),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  build: {
    rollupOptions: {
      external: ['/config/settings.json'],
      output: {
        manualChunks(id) {
          return 'App';
        }
      }
    }
  }
})

Which results on npm run build to this:

vite v5.4.14 building for production...
✓ 875 modules transformed.
dist/index.php                                              0.99 kB
dist/assets/materialdesignicons-webfont-Dp5v-WZN.woff2    403.22 kB
dist/assets/materialdesignicons-webfont-PXm3-2wK.woff     587.98 kB
dist/assets/materialdesignicons-webfont-B7mPwVP_.ttf    1,307.66 kB
dist/assets/materialdesignicons-webfont-CSr8KVlo.eot    1,307.88 kB
dist/assets/index-B9hCvS5B.css                            774.23 kB │ gzip: 110.89 kB
dist/assets/index.php-Cxh_CgE8.js                         576.45 kB │ gzip: 184.18 kB

The size of the materialdesignicons are enormous compared to the small app size. How can I reduce the size of the fonts? Is this a vuetify issue?

EDIT My main.js


//Vuetify
import '@mdi/font/css/materialdesignicons.css'
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'

const vuetify = createVuetify({
  components,
  directives,
  locale: {
    messages: { de, en }
  }
})

app
  .use(createPinia())
  .use(vuetify)
  .use(router)

This is my vite-config.js

import { fileURLToPath, URL } from 'node:url'

import { defineConfig, splitVendorChunkPlugin } from 'vite'
import vue from '@vitejs/plugin-vue'
import usePHP from 'vite-plugin-php'

export default defineConfig({
  plugins: [
    usePHP({
      binary: 'C:/tools/php83/php.exe',
    }),
    vue({
      template: {
        compilerOptions: {
          isCustomElement: (tag) => ['v-list-item-content', 'v-list-item-group'].includes(tag),
        }
      }
    }),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  build: {
    rollupOptions: {
      external: ['/config/settings.json'],
      output: {
        manualChunks(id) {
          return 'App';
        }
      }
    }
  }
})

Which results on npm run build to this:

vite v5.4.14 building for production...
✓ 875 modules transformed.
dist/index.php                                              0.99 kB
dist/assets/materialdesignicons-webfont-Dp5v-WZN.woff2    403.22 kB
dist/assets/materialdesignicons-webfont-PXm3-2wK.woff     587.98 kB
dist/assets/materialdesignicons-webfont-B7mPwVP_.ttf    1,307.66 kB
dist/assets/materialdesignicons-webfont-CSr8KVlo.eot    1,307.88 kB
dist/assets/index-B9hCvS5B.css                            774.23 kB │ gzip: 110.89 kB
dist/assets/index.php-Cxh_CgE8.js                         576.45 kB │ gzip: 184.18 kB

The size of the materialdesignicons are enormous compared to the small app size. How can I reduce the size of the fonts? Is this a vuetify issue?

EDIT My main.js


//Vuetify
import '@mdi/font/css/materialdesignicons.css'
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'

const vuetify = createVuetify({
  components,
  directives,
  locale: {
    messages: { de, en }
  }
})

app
  .use(createPinia())
  .use(vuetify)
  .use(router)

Share Improve this question edited Feb 6 at 11:56 Moritz Ringler 16.1k10 gold badges27 silver badges45 bronze badges asked Feb 1 at 12:27 theking2theking2 2,8702 gold badges34 silver badges48 bronze badges 5
  • The recommended way is to use svg icons, as you don't have to include the full icon set. Instead, only the icons you actually use will be bundled (see docs) – Moritz Ringler Commented Feb 2 at 16:58
  • Yeah I agree but it seems vuetify uses these (?) – theking2 Commented Feb 3 at 8:27
  • I found this in the vuetify docs. – theking2 Commented Feb 3 at 10:24
  • Using the font file is the easiest way, but SVG is recommended to reduce built size in production. Since font files are cached, clients typically only download them once, so for projects with a limited set of users (most business projects probably), this is often acceptable (no first time visitors wondering what weird page they landed at). – Moritz Ringler Commented Feb 3 at 10:48
  • @MoritzRingler thanks! I've provided an example in my answer. – theking2 Commented Feb 3 at 12:09
Add a comment  | 

2 Answers 2

Reset to default 0

In order to prevent inclusion of all icons consider including only those you need and not use <v-icon></v-icon> but instead use @mdi/js

pnpm install @mdi/js  

To make this easy create component Icon.vue

<script setup>
defineProps({
    path: String,
    fill: String,
    size: {
        type: [String, Number],
        default: 24
    }
});
</script>

<template>
    <svg :width="size" :height="size" viewBox="0 0 24 24">
        <path :d="path" :fill="fill" />
    </svg>
</template>

and use it in your template:

<template>

<Icon :path="mdiAccount"  fill="red" size="60"/>

</template>
<script>
import { mdiAccount } from "@mdi/js";
import Icon from '@/components/Icon.vue';
</script>

Of course you can fill from properties or computed value

After that make sure to remove the fonts with pnpm uninstall @mdi/font

In Vuetify, an icon setup consists of three parts:

  • an icon source (e.g. an icon font used through css classes)
  • a component that knows how to display the icons from the source (i.e. to render an <i> tag with the css class of the icon)
  • a record binding icons to named aliases

The component and the aliases depend on the source, Vuetify provides implementations for Material Design Icons (MDI) and Font Awesome (FA), both css and svg. For other icons, you have to provide your own icon component and alias mapping (see docs for creating a custom icon set).

The default is MDI css font, Vuetify expects the css files being available. Usually, that means you have import '@mdi/font/css/materialdesignicons.css' somewhere in your project, the actual font files (woff, ttf, etc.) are then added to your bundle along the CSS file. Clients will load the fonts file they work best with (usually woff2 I think, but it might be declaration order in CSS, not sure).

So to switch from MDI css, follow these steps:

  1. remove the import of materialdesignicons.css
  2. install the icon library you want to use
  3. register component and alias declaration in the icons part of the Vuetify configuration passed to createVuetify(). For MDI SVG, this looks as in the documentation:
import { aliases, mdi } from 'vuetify/iconsets/mdi-svg'

export default createVuetify({
  icons: {
    defaultSet: 'mdi', // refers to a value in "sets" below
    aliases, // <--- the aliases, should match the defaultSet
    sets: {
      mdi, // <--- the icon component
    },
  },
})

Look at vuetify/iconsets/mdi-svg to see the aliases, it is a simple object, binding names to SVG pathes. The component exported as mdi puts those SVG pathes into a SVG element (same as the Icon.vue component in your answer):

const aliases: IconAliases = {
  collapse: 'svg:M7.41,15.41L12,10.83L16.59,15.41L18,14L12,8L6,14L7.41,15.41Z',
  complete: 'svg:M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z',
  ...
}

const mdi: IconSet = {
  component: VSvgIcon,
}

Implementation of VSvgIcon can be found here.

  1. Make sure icons you use in your project are available.

For example, <v-icon icon="mdi-home" /> will not work anymore when you removed the CSS file and changed the component (you'll get a SVG with a path d="mdi-home"). Import the declaration (the SVG path) into the context where you use VIcon. To import into context:

<template>
  <v-icon :icon="mdiAccount" />
</template>

<script setup>
  import { mdiAccount } from '@mdi/js'
</script>

It is also possible to extend aliases and work with placeholders, which is the key from aliases prefixed with a $ (see documentation for an example).

Registering multiple icon sets basically means to register multiple of those icon components, you can tell VIcon which component to use through prefixes (see docs).

Hope this clears things up.

发布评论

评论列表(0)

  1. 暂无评论