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)
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:
<i>
tag with the css class of the icon)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:
materialdesignicons.css
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.
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.