perf: Lucide subpath imports to split 748 KB icon chunk

Barrel `from '@lucide/svelte'` imports pulled every referenced icon into
one shared 748 KB client chunk. Switch every call site to per-icon
subpaths (`@lucide/svelte/icons/<kebab-name>`) so Vite tree-shakes each
icon independently. Also logs the TODO list for the perf audit so we
don't lose track.

- 46 files, 106 unique icons
- single `Minus as MinusIcon` alias preserved
- Lucide-internal aliases (`AlertTriangle`, `BarChart3`) resolve through
  Lucide's own re-export shims; no behavioral change
This commit is contained in:
2026-04-23 14:52:39 +02:00
parent ebc59cbf6b
commit abb59f46a6
48 changed files with 1582 additions and 57 deletions
+3 -2
View File
@@ -1,6 +1,7 @@
<script>
import { ChevronLeft, ChevronRight, Calendar } from '@lucide/svelte';
import ChevronLeft from '@lucide/svelte/icons/chevron-left';
import ChevronRight from '@lucide/svelte/icons/chevron-right';
import Calendar from '@lucide/svelte/icons/calendar';
let { value = $bindable(''), lang = 'en', min = '', max = '' } = $props();
let open = $state(false);
+5 -2
View File
@@ -1,7 +1,10 @@
<script lang="ts">
import type { Snippet, Component } from 'svelte';
import { Lock, Ban, SearchX, TriangleAlert, CircleAlert } from '@lucide/svelte';
import Lock from '@lucide/svelte/icons/lock';
import Ban from '@lucide/svelte/icons/ban';
import SearchX from '@lucide/svelte/icons/search-x';
import TriangleAlert from '@lucide/svelte/icons/triangle-alert';
import CircleAlert from '@lucide/svelte/icons/circle-alert';
interface BibleQuote {
text: string;
reference: string;
+3 -1
View File
@@ -1,6 +1,8 @@
<script>
import { themeStore } from '$lib/stores/theme.svelte';
import { Sun, Moon, SunMoon } from '@lucide/svelte';
import Sun from '@lucide/svelte/icons/sun';
import Moon from '@lucide/svelte/icons/moon';
import SunMoon from '@lucide/svelte/icons/sun-moon';
</script>
<style>
+1 -1
View File
@@ -1,5 +1,5 @@
<script>
import { X } from '@lucide/svelte';
import X from '@lucide/svelte/icons/x';
import { getToasts } from '$lib/js/toast.svelte';
const toasts = getToasts();
@@ -2,7 +2,9 @@
import { browser } from '$app/environment';
import { getAngelusStreak, getCurrentTimeSlot, type TimeSlot } from '$lib/stores/angelusStreak.svelte';
import StreakAura from '$lib/components/faith/StreakAura.svelte';
import { Coffee, Sun, Moon } from '@lucide/svelte';
import Coffee from '@lucide/svelte/icons/coffee';
import Sun from '@lucide/svelte/icons/sun';
import Moon from '@lucide/svelte/icons/moon';
import { tick, onMount } from 'svelte';
let burst = $state(false);
@@ -1,7 +1,14 @@
<script>
import { getFilterOptionsAll, searchAllExercises } from '$lib/data/exercisedb';
import { translateTerm } from '$lib/data/exercises';
import { Search, X, Cable, Cog, Dumbbell, PersonStanding, Shapes, Weight } from '@lucide/svelte';
import Search from '@lucide/svelte/icons/search';
import X from '@lucide/svelte/icons/x';
import Cable from '@lucide/svelte/icons/cable';
import Cog from '@lucide/svelte/icons/cog';
import Dumbbell from '@lucide/svelte/icons/dumbbell';
import PersonStanding from '@lucide/svelte/icons/person-standing';
import Shapes from '@lucide/svelte/icons/shapes';
import Weight from '@lucide/svelte/icons/weight';
import { page } from '$app/stores';
import { detectFitnessLang, t } from '$lib/js/fitnessI18n';
+4 -1
View File
@@ -2,7 +2,10 @@
import { page } from '$app/stores';
import { browser } from '$app/environment';
import { untrack } from 'svelte';
import { Heart, ExternalLink, ScanBarcode, X } from '@lucide/svelte';
import Heart from '@lucide/svelte/icons/heart';
import ExternalLink from '@lucide/svelte/icons/external-link';
import ScanBarcode from '@lucide/svelte/icons/scan-barcode';
import X from '@lucide/svelte/icons/x';
import { detectFitnessLang, fitnessSlugs, t } from '$lib/js/fitnessI18n';
import MacroBreakdown from './MacroBreakdown.svelte';
@@ -1,7 +1,9 @@
<script>
import { detectFitnessLang } from '$lib/js/fitnessI18n';
import { page } from '$app/stores';
import { Beef, Droplet, Wheat } from '@lucide/svelte';
import Beef from '@lucide/svelte/icons/beef';
import Droplet from '@lucide/svelte/icons/droplet';
import Wheat from '@lucide/svelte/icons/wheat';
import RingGraph from './RingGraph.svelte';
/**
@@ -1,5 +1,8 @@
<script>
import { Coffee, Sun, Moon, Cookie } from '@lucide/svelte';
import Coffee from '@lucide/svelte/icons/coffee';
import Sun from '@lucide/svelte/icons/sun';
import Moon from '@lucide/svelte/icons/moon';
import Cookie from '@lucide/svelte/icons/cookie';
import { t } from '$lib/js/fitnessI18n';
/** @type {{ value?: 'breakfast' | 'lunch' | 'dinner' | 'snack', lang?: 'en' | 'de', onchange?: (meal: 'breakfast' | 'lunch' | 'dinner' | 'snack') => void }} */
@@ -1,6 +1,12 @@
<script>
import { t } from '$lib/js/fitnessI18n';
import { Trash2, Plus, Pencil, UserPlus, X, ChevronLeft, ChevronRight } from '@lucide/svelte';
import Trash2 from '@lucide/svelte/icons/trash-2';
import Plus from '@lucide/svelte/icons/plus';
import Pencil from '@lucide/svelte/icons/pencil';
import UserPlus from '@lucide/svelte/icons/user-plus';
import X from '@lucide/svelte/icons/x';
import ChevronLeft from '@lucide/svelte/icons/chevron-left';
import ChevronRight from '@lucide/svelte/icons/chevron-right';
import DatePicker from '$lib/components/DatePicker.svelte';
import { toast } from '$lib/js/toast.svelte';
import { confirm } from '$lib/js/confirmDialog.svelte';
@@ -1,5 +1,10 @@
<script>
import { Plus, ChevronDown, Sparkles, Beef, Droplet, Wheat } from '@lucide/svelte';
import Plus from '@lucide/svelte/icons/plus';
import ChevronDown from '@lucide/svelte/icons/chevron-down';
import Sparkles from '@lucide/svelte/icons/sparkles';
import Beef from '@lucide/svelte/icons/beef';
import Droplet from '@lucide/svelte/icons/droplet';
import Wheat from '@lucide/svelte/icons/wheat';
import { untrack } from 'svelte';
import { toast } from '$lib/js/toast.svelte';
import { t } from '$lib/js/fitnessI18n';
@@ -1,7 +1,12 @@
<script>
import { page } from '$app/stores';
import { getExerciseById, getExerciseMetrics } from '$lib/data/exercises';
import { Clock, Weight, Trophy, Route, Gauge, Flame } from '@lucide/svelte';
import Clock from '@lucide/svelte/icons/clock';
import Weight from '@lucide/svelte/icons/weight';
import Trophy from '@lucide/svelte/icons/trophy';
import Route from '@lucide/svelte/icons/route';
import Gauge from '@lucide/svelte/icons/gauge';
import Flame from '@lucide/svelte/icons/flame';
import { detectFitnessLang, fitnessSlugs } from '$lib/js/fitnessI18n';
const lang = $derived(detectFitnessLang($page.url.pathname));
+4 -1
View File
@@ -1,5 +1,8 @@
<script>
import { Check, X, Play, Square } from '@lucide/svelte';
import Check from '@lucide/svelte/icons/check';
import X from '@lucide/svelte/icons/x';
import Play from '@lucide/svelte/icons/play';
import Square from '@lucide/svelte/icons/square';
import { METRIC_LABELS } from '$lib/data/exercises';
import RestTimer from './RestTimer.svelte';
import { page } from '$app/stores';
@@ -1,6 +1,8 @@
<script>
import { Cloud, CloudOff, RefreshCw, AlertTriangle } from '@lucide/svelte';
import Cloud from '@lucide/svelte/icons/cloud';
import CloudOff from '@lucide/svelte/icons/cloud-off';
import RefreshCw from '@lucide/svelte/icons/refresh-cw';
import AlertTriangle from '@lucide/svelte/icons/alert-triangle';
/** @type {{ status: string }} */
let { status } = $props();
</script>
@@ -1,6 +1,7 @@
<script>
import { getExerciseById } from '$lib/data/exercises';
import { EllipsisVertical, MapPin } from '@lucide/svelte';
import EllipsisVertical from '@lucide/svelte/icons/ellipsis-vertical';
import MapPin from '@lucide/svelte/icons/map-pin';
import { page } from '$app/stores';
import { detectFitnessLang, t } from '$lib/js/fitnessI18n';
@@ -1,6 +1,5 @@
<script>
import { X } from '@lucide/svelte';
import X from '@lucide/svelte/icons/x';
let { src, poster = '', onClose } = $props();
/** @param {KeyboardEvent} e */
+2 -1
View File
@@ -1,6 +1,7 @@
<script>
import { goto } from '$app/navigation';
import { Play, Pause } from '@lucide/svelte';
import Play from '@lucide/svelte/icons/play';
import Pause from '@lucide/svelte/icons/pause';
import SyncIndicator from '$lib/components/fitness/SyncIndicator.svelte';
import { page } from '$app/stores';
import { detectFitnessLang, t } from '$lib/js/fitnessI18n';
@@ -1,5 +1,6 @@
<script>
import { UtensilsCrossed, X } from '@lucide/svelte';
import UtensilsCrossed from '@lucide/svelte/icons/utensils-crossed';
import X from '@lucide/svelte/icons/x';
import { toast } from '$lib/js/toast.svelte';
let {
@@ -4,8 +4,12 @@ import Pen from '$lib/assets/icons/Pen.svelte'
import Cross from '$lib/assets/icons/Cross.svelte'
import Plus from '$lib/assets/icons/Plus.svelte'
import Check from '$lib/assets/icons/Check.svelte'
import { Timer, Wheat, Croissant, Flame, CookingPot, UtensilsCrossed } from '@lucide/svelte';
import Timer from '@lucide/svelte/icons/timer';
import Wheat from '@lucide/svelte/icons/wheat';
import Croissant from '@lucide/svelte/icons/croissant';
import Flame from '@lucide/svelte/icons/flame';
import CookingPot from '@lucide/svelte/icons/cooking-pot';
import UtensilsCrossed from '@lucide/svelte/icons/utensils-crossed';
import "$lib/css/action_button.css"
import { do_on_key } from '$lib/components/recipes/do_on_key.js'
@@ -1,5 +1,10 @@
<script>
import { Timer, Wheat, Croissant, Flame, CookingPot, UtensilsCrossed } from '@lucide/svelte';
import Timer from '@lucide/svelte/icons/timer';
import Wheat from '@lucide/svelte/icons/wheat';
import Croissant from '@lucide/svelte/icons/croissant';
import Flame from '@lucide/svelte/icons/flame';
import CookingPot from '@lucide/svelte/icons/cooking-pot';
import UtensilsCrossed from '@lucide/svelte/icons/utensils-crossed';
let { data } = $props();
// svelte-ignore state_referenced_locally
@@ -1,5 +1,6 @@
<script>
import { ChevronLeft, ChevronRight } from '@lucide/svelte';
import ChevronLeft from '@lucide/svelte/icons/chevron-left';
import ChevronRight from '@lucide/svelte/icons/chevron-right';
import { getStickerById } from '$lib/utils/stickers';
import {
startOfMonth, endOfMonth, startOfWeek, endOfWeek,
+14 -2
View File
@@ -1,6 +1,18 @@
<script>
import { X, Sparkles, Wind, Bath, UtensilsCrossed, CookingPot, WashingMachine,
Flower2, Droplets, Leaf, ShoppingCart, Trash2, Shirt, Brush } from '@lucide/svelte';
import X from '@lucide/svelte/icons/x';
import Sparkles from '@lucide/svelte/icons/sparkles';
import Wind from '@lucide/svelte/icons/wind';
import Bath from '@lucide/svelte/icons/bath';
import UtensilsCrossed from '@lucide/svelte/icons/utensils-crossed';
import CookingPot from '@lucide/svelte/icons/cooking-pot';
import WashingMachine from '@lucide/svelte/icons/washing-machine';
import Flower2 from '@lucide/svelte/icons/flower-2';
import Droplets from '@lucide/svelte/icons/droplets';
import Leaf from '@lucide/svelte/icons/leaf';
import ShoppingCart from '@lucide/svelte/icons/shopping-cart';
import Trash2 from '@lucide/svelte/icons/trash-2';
import Shirt from '@lucide/svelte/icons/shirt';
import Brush from '@lucide/svelte/icons/brush';
import ProfilePicture from '$lib/components/cospend/ProfilePicture.svelte';
import Toggle from '$lib/components/Toggle.svelte';
import DatePicker from '$lib/components/DatePicker.svelte';