adeo / mozaic-design-system

Mozaic Design System
https://mozaic.adeo.cloud
Apache License 2.0
68 stars 17 forks source link

feat(icon): provide splitte icon files for Vue.js #1417

Open pinguet62 opened 1 year ago

pinguet62 commented 1 year ago

I want to propose an evolution/improvement on

Icon set

Description

Naming convension

Currently all icons are listed in icon/js/icon.js file, where each couple of name/size has constant name with convension {name}{size} 👍 â„č Name comes from catalog

Problem

In JS, the solution to load 1 icon is to load the entire file, and filter constantes following previous convension. It's not a good practice regarding application loading: the bundle file is very big (>1Mo 😹)

SVG files

A solution is to load directly SVG from /icons/svg/*.svg. But the problem is filename doesn't respect the previous convension: they have different prefix.

Describe the solution you would like

Create new folder, specifically for Vue.js, will create another one more name for an icon. And there are already too many cases: icon name ≠ React/vue name ≠ Web Component name ≠ Svg file name ...

So in my opinion, rename icons to follow the same convension is the best solution 👍

Describe the alternatives you considered

No response

Additional comments

⚠ There is a difference between inline SVG in icons/js/icons.js who declare the size attribute, and icons/svg/*.svg who don't declare this size attribute.

pinguet62 commented 1 year ago

@tiloyi pour les icones et SVG :

<component :is="icon" />
const iconName = computed(() => `Device_${props.name}_${props.size}px`);

⚠ C'est ici que le prĂ©fix sur le filename du SVG pose soucis

Version directe :

const icon = defineAsyncComponent(() => {
  return import(`/node_modules/@mozaic-ds/icons/svg/${iconName.value}.svg`);
});

Version "distionnaire" :

const modules = import.meta.glob('/node_modules/@mozaic-ds/icons/svg/*.svg')
const icon = defineAsyncComponent(async () => {
  const moduleName = `/node_modules/@mozaic-ds/icons/svg/${iconName.value}.svg`
  return await modules[moduleName]()
});

⚠ NĂ©cessite vite-svg-loader, mais Ă  mon avis il y aurait moyen de s'en passer en chargeant dynamiquement les modules diffĂ©remment ou en affichant le <component diffĂ©rement

pinguet62 commented 1 year ago

⚠ NĂ©cessite vite-svg-loader, mais Ă  mon avis il y aurait moyen de s'en passer en chargeant dynamiquement les modules diffĂ©remment ou en affichant le <component diffĂ©rement

Je suis bĂȘte, je l'avais fait sans plugin :

<template>
  <img :src="svg"/>
</template>
import {onBeforeMount, ref} from 'vue'

const props = defineProps({
  svgFile: {
    type: String,
    required: true,
  },
  // native attributes
  alt: String,
})

const svg = ref<string>();

onBeforeMount(async () => {
  const svgModuleFactories = import.meta.glob('/node_modules/@mozaic-ds/icons/svg/*.svg')
  const svgModuleFactory = svgModuleFactories[`/node_modules/@mozaic-ds/icons/svg/${props.svgFile}`]
  const svgModule = await svgModuleFactory() as { default: string }
  svg.value = svgModule.default
})
pinguet62 commented 1 year ago

https://github.com/adeo/pricely/tree/main/sspm-front/src/mozaic/MIcon ✅ tree shaking ✅ pas de plugin supplĂ©mentaire ✅ 0 breaking change

â„č serait idĂ©al : harmoniser les noms d'icone entre fichiers SVG, Vue.js, WebComponents, React

anthony-melique commented 11 months ago

Hello, je viens de tester cette solution avec un composant de test et Ă  priori, il y a encore un surpoids significatif, mĂȘme le gain est dĂ©jĂ  trĂšs apprĂ©ciable.

Voici les différents chiffres obtenu lors de mes tests :

Sans icĂŽnes dans l'application (54kB) : image

Avec le composant MIcon original (1169 kB) : image

Avec cette solution (261 kB) : image

Est ce que tu remarque le mĂȘme genre de chiffre ?

pinguet62 commented 11 months ago

Effectivement j'ai Ă©galement un surplus de 200kB :

Si je ne dis pas de bĂȘtise :

Sachant qu'il y a 1441 icones : c'est cohĂ©rent 👍 Et ça, Ă  part n'utiliser qu'1 seul SVG pour toutes les tailles (plutĂŽt qu'1 par taille) il n'y a pas rĂ©ellement de solution !