Files
recipe-app/.kilo/plans/flutter-lighthouse.md
T
Nils-Johan Gynther 69bcc3e342
Test Suite / backend-pr-quick (push) Has been skipped
Test Suite / quick-import-pr-quick (push) Has been skipped
Test Suite / backend-full (push) Successful in 14m6s
Test Suite / flutter-quality (push) Failing after 4m44s
feat(web): improve web build configuration and accessibility
- Add source maps and web renderer build arguments with defaults
- Configure Caddy with CSP headers, cache policies, and service worker handling
- Defer loading of import screen for performance optimization
- Add semantic labels to icons for accessibility
- Update web index.html with Swedish language, meta tags, and description
- Add robots.txt and lighthouse configuration
- Add new planning documents and archive entries
2026-05-23 18:04:27 +02:00

707 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
🚹 Kritiska Problem (Prioritet 1: Fixa Omedelbart)
Dessa problem pÄverkar anvÀndarupplevelsen mest och bör ÄtgÀrdas först.
1. Prestanda: LÄngsam inladdning & Stora Filer
🔮 Problem:
Total storlek: 2,978 KiB (för stor för en webbapp).
/main.dart.js: 1,216 KiB (Flutter’s kompilade JavaScript).
canvaskit.wasm: 1,592 KiB (Flutter’s CanvasKit-renderare).
MaterialIcons-Regular.otf: 9.8 KiB (ikoner).
Largest Contentful Paint (LCP) misslyckades (tidsgrÀns överskreds).
Total Blocking Time (TBT) misslyckades (lÄnga JavaScript-uppgifter blockerar huvudtrÄden).
JavaScript-exekveringstid: 1.8s (för lÄngt).
🟱 Lösningar:
A. Optimera Flutter för Web
Flutter-webbappar Àr tyngre Àn traditionella webbappar pÄ grund av CanvasKit. HÀr Àr hur du minskar storleken:
AnvÀnd HTML-renderaren istÀllet för CanvasKit
CanvasKit ger bÀttre grafik men Àr mycket tyngre.
Ändra i index.html:
html
Copy
<script>
window.flutterConfiguration = {
renderMode: "html", // IstÀllet för "canvas" (CanvasKit)
};
</script>
Fördel: Minskar storleken med ~1.5MB (WASM-filen laddas inte).
Nackdel: Vissa avancerade animationer/efekter fungerar inte lika bra.
Aktivera komprimering (GZIP/Brotli)
Din server skickar okomprimerade filer.
Lösning:
Nginx: LĂ€gg till i konfigurationen:
nginx
Copy
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
brotli on;
brotli_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
Apache: AnvÀnd mod_deflate eller mod_brotli.
Cloudflare: Aktivera "Brotli Compression" i instÀllningarna.
Cachea statiska resurser
Problem: /main.dart.js och flutter_bootstrap.js har ingen cache-TTL.
Lösning: LÀgg till Cache-Control-headers:
nginx
Copy
location ~* \.(js|css|png|jpg|jpeg|gif|ico|wasm|otf)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
Besparing: ~1.2MB vid upprepade besök.
Dela upp JavaScript-koden (Code Splitting)
Flutter laddar allt i en stor fil (main.dart.js).
Lösning: AnvÀnd deferred imports för att ladda funktioner pÄ begÀran:
dart
Copy
// I din Dart-kod:
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:my_app/receipt_import.dart' deferred as receipt_import;
// Ladda endast nÀr behövs:
Future<void> loadReceiptImport() async {
await receipt_import.loadLibrary();
}
Effekt: Minskar initial laddningstid.
Optimera bilder
Problem: Bilder laddas inte optimalt.
Lösning:
AnvÀnd flutter_image_compress för att komprimera bilder innan uppladdning.
För webb: AnvÀnd <picture> med srcset för responsiva bilder.
Exempel:
html
Copy
<picture>
<source srcset="image-480w.jpg" media="(max-width: 600px)">
<source srcset="image-800w.jpg" media="(max-width: 1200px)">
<img src="image-1200w.jpg" alt="Receptbild">
</picture>
B. FörbÀttra Laddningsordningen
Fördröj laddning av icke-kritiska resurser
Ladda canvaskit.wasm efter att sidan har renderats:
html
Copy
<script>
window.addEventListener('load', () => {
const script = document.createElement('script');
script.src = 'https://www.gstatic.com/canvaskit/v1/chromium/canvaskit.wasm';
document.body.appendChild(script);
});
</script>
AnvÀnd preload för kritiska resurser
LĂ€gg till i <head>:
html
Copy
<link rel="preload" href="/main.dart.js" as="script">
<link rel="preload" href="/flutter_bootstrap.js" as="script">
2. TillgÀnglighet: GrundlÀggande Problem
🔮 Problem:
[user-scalable="no"] i viewport-meta-taggen
Varför det Àr dÄligt: AnvÀndare med nedsatt syn kan inte zooma in.
Lösning: Ta bort user-scalable="no":
html
Copy
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Saknas alt-texter pÄ bilder
Problem: SkÀrmlÀsare kan inte beskriva bilder.
Lösning: LÀgg till alt-texter i Flutter:
dart
Copy
Image.network(
'https://example.com/recept.jpg',
semanticLabel: 'Bild pÄ lasagne med ost och tomatsÄs', // Alt-text
),
Saknas lang-attribut
Problem: SkÀrmlÀsare vet inte vilket sprÄk sidan anvÀnder.
Lösning: LÀgg till i <html>:
html
Copy
<html lang="sv">
3. SEO: GrundlÀggande Problem
🔮 Problem:
Saknas meta description
Varför det Àr dÄligt: Sökmotorer visar ingen beskrivning i resultaten.
Lösning: LÀgg till i <head>:
html
Copy
<meta name="description" content="UpptÀck och lagra dina recept. Importera kvitton och hÄll koll pÄ ditt kylskÄp med vÄr smarta app.">
Ogiltig robots.txt
Problem: Din robots.txt innehÄller HTML-kod istÀllet för korrekt syntax.
Lösning: Skapa en korrekt robots.txt:
text
Copy
User-agent: *
Allow: /
Sitemap: https://recept.gynther.se/sitemap.xml
⚠ Viktiga FörbĂ€ttringar (Prioritet 2: Fixa Inom 1-2 Veckor)
Dessa problem pÄverkar anvÀndarupplevelsen och SEO, men Àr inte lika kritiska.
1. Prestanda: JavaScript & Rendering
🟡 Problem:
LÄng JavaScript-exekveringstid (1.8s)
Orsak: Flutter’s main.dart.js tar 1.7s att parsas och exekveras.
Minify CSS/JS misslyckades
Flutter genererar redan minifierad kod, men du kan optimera vidare.
🟱 Lösningar:
Aktivera Flutter’s --release flagga
Bygg appen med:
bash
Copy
flutter build web --release
Detta genererar optimerad och minifierad kod.
AnvÀnd flutter build web --no-source-maps
Source maps ökar filstorleken. Ta bort dem i produktion:
bash
Copy
flutter build web --no-source-maps
Fördröj laddning av icke-kritisk JavaScript
AnvÀnd defer eller async för skript som inte behövs omedelbart:
html
Copy
<script src="/flutter_bootstrap.js" defer></script>
Reducera DOM-storlek
Problem: Din sida har 21 element med en max-djup pÄ 7 (acceptabelt, men kan optimeras).
Lösning: Undvik onödiga Container-widgets i Flutter. AnvÀnd const widgets dÀr möjligt.
2. TillgÀnglighet: Interaktiva Element
🟡 Problem:
Saknas focus-indikatorer
AnvÀndare som navigerar med tangentbord ser inte vilka element som Àr fokuserade.
Saknas aria-label pÄ anpassade knappar
SkÀrmlÀsare vet inte vad knapparna gör.
🟱 Lösningar:
LĂ€gg till focus-stilar i CSS
Exempel:
css
Copy
button:focus, [tabindex="0"]:focus {
outline: 2px solid #4285F4;
outline-offset: 2px;
}
AnvÀnd semantics i Flutter för tillgÀnglighet
Exempel för en knapp:
dart
Copy
Semantics(
label: 'Importera kvitto',
button: true,
child: ElevatedButton(
onPressed: () => _importReceipt(),
child: Text('Importera'),
),
),
LÀgg till aria-label pÄ ikonknappar
Exempel:
dart
Copy
IconButton(
icon: Icon(Icons.upload),
onPressed: () => _uploadFile(),
tooltip: 'Ladda upp kvitto', // Visas pÄ hover
semanticsLabel: 'Ladda upp kvitto', // För skÀrmlÀsare
),
3. SĂ€kerhet: Content Security Policy (CSP)
🟡 Problem:
Saknas CSP-header
Din sida Àr sÄrbar för XSS-attacker (Cross-Site Scripting).
🟱 Lösning:
LĂ€gg till en stark CSP i din serverkonfiguration:
nginx
Copy
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.gstatic.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://*.gstatic.com; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://recept.gynther.se; frame-src 'none'; object-src 'none';";
Förklaring:
script-src: TillÄter skript frÄn self och gstatic.com (för Flutter).
unsafe-inline: NödvÀndigt för Flutter (men försök minska anvÀndningen).
img-src: TillÄter bilder frÄn self och gstatic.com.
📌 Mindre Problem (Prioritet 3: Fixa NĂ€r Tid Finns)
Dessa Àr förbÀttringar som inte Àr kritiska men kan förbÀttra UX och SEO.
1. Prestanda: Bildoptimering
Problem: Bilder laddas utan width och height (orsakar layout shifts).
Lösning: AnvÀnd Image.network med explicit storlek:
dart
Copy
Image.network(
'https://example.com/recept.jpg',
width: 300,
height: 200,
fit: BoxFit.cover,
),
2. SEO: Structured Data
Problem: Saknas schema.org-markup för recept (gör att Google kan visa "rich results").
Lösning: LÀgg till JSON-LD i <head>:
html
Copy
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Recipe",
"name": "Lasagne",
"author": {
"@type": "Person",
"name": "Nils-Johan Gynther"
},
"datePublished": "2026-05-21",
"description": "En klassisk lasagne med köttfÀrs och bechamelsÄs.",
"prepTime": "PT30M",
"cookTime": "PT45M",
"totalTime": "PT1H15M",
"recipeYield": "4 portioner",
"recipeCategory": "Middag",
"recipeCuisine": "Italiensk",
"keywords": "lasagne, pasta, köttfÀrs",
"recipeIngredient": ["500g köttfÀrs", "250g ost", "1 paket lasagneplattor"],
"recipeInstructions": [
{
"@type": "HowToStep",
"name": "Börja med att frÀsa köttfÀrsen.",
"text": "FrÀs köttfÀrsen i en stekpanna tills den Àr genomstekt."
},
{
"@type": "HowToStep",
"name": "Lagra lasagnen i ugnen.",
"text": "Skikta lasagneplattor, köttfÀrs och sÄs i en ugnsform. GrÀdda i 45 minuter pÄ 200°C."
}
]
}
</script>
Effekt: Google kan visa receptkort i sökresultaten (ökad klickfrekvens).
3. TillgÀnglighet: Logisk Tab-Order
Problem: AnvÀndare kan tabba till element som Àr dolda eller off-screen.
Lösning: AnvÀnd FocusableAction i Flutter för att kontrollera tab-order:
dart
Copy
FocusableActionDetector(
autofocus: true,
onFocusChange: (hasFocus) {
if (hasFocus) {
// Hantera focus
}
},
child: MyWidget(),
),
📊 Sammanfattning av Prioriteringar
Prioritet
Problem
Lösning
Tidsuppskattning
Impact
1 (Kritisk)
Stora filer (2.9MB)
Byt till HTML-renderare, aktivera GZIP, cachea resurser
1-2 timmar
⭐⭐⭐⭐⭐ (Hög)
1 (Kritisk)
LÄng JavaScript-exekvering (1.8s)
Code splitting, defer non-critical JS
2-4 timmar
⭐⭐⭐⭐⭐ (Hög)
1 (Kritisk)
user-scalable="no"
Ta bort frÄn viewport-meta-taggen
5 minuter
⭐⭐⭐⭐ (Hög)
1 (Kritisk)
Saknas meta description
LĂ€gg till i
5 minuter
⭐⭐⭐ (Medel)
1 (Kritisk)
Ogiltig robots.txt
Skapa korrekt robots.txt
10 minuter
⭐⭐⭐ (Medel)
2 (Viktig)
Saknas CSP-header
LĂ€gg till i serverkonfigurationen
1 timme
⭐⭐⭐⭐ (Hög)
2 (Viktig)
Saknas alt-texter
LĂ€gg till semanticLabel i Flutter
1-2 timmar
⭐⭐⭐ (Medel)
2 (Viktig)
LÄng DOM-parsning
Minska onödiga widgets
1-2 timmar
⭐⭐ (LÄg)
3 (Mindre)
Saknas structured data
LÀgg till JSON-LD för recept
1 timme
⭐⭐ (LÄg)
đŸ› ïž Konkreta ÅtgĂ€rder (Steg-för-Steg)
Steg 1: Fixa Prestanda (1-2 dagar)
Byt till HTML-renderare (sparar ~1.5MB):
Ändra index.html som visat ovan.
Aktivera GZIP/Brotli pÄ servern.
Cachea statiska filer (1 Är för JS/CSS).
Bygg appen med --release:
bash
Copy
flutter build web --release --no-source-maps
Ladd upp den optimerade versionen till din server.
Steg 2: Fixa TillgÀnglighet (1 dag)
Ta bort user-scalable="no" frÄn viewport.
LĂ€gg till lang="sv" i <html>.
LÀgg till alt-texter pÄ alla bilder.
LÀgg till semanticsLabel pÄ knappar och ikoner.
Steg 3: Fixa SEO (1 dag)
LĂ€gg till meta description.
Fixa robots.txt.
LÀgg till structured data för recept.
Steg 4: SĂ€kerhet (1 timme)
LĂ€gg till CSP-header i serverkonfigurationen.
📈 FörvĂ€ntade Resultat
MĂ€tning
Nuvarande
Efter Fixar
FörbÀttring
Total storlek
2,978 KiB
~500-800 KiB
-70%
Laddningstid (LCP)
Timeout
< 2.5s
✅ Fixad
JavaScript-exekvering
1.8s
< 1s
-45%
TillgÀnglighet
82/100
95+/100
+15 poÀng
SEO
6/10
9/10
+50%
SĂ€kerhet
Risk för XSS
Skyddad
✅ Fixad
🔍 Hur du Testar FörbĂ€ttringarna
Kör Lighthouse igen i Chrome DevTools (F12 → "Lighthouse").
Testa pĂ„ mobil (anvĂ€nd Chrome’s "Device Toolbar").
AnvÀnd WebPageTest (webpagetest.org) för att mÀta prestanda globalt.
Testa tillgÀnglighet med:
WAVE Evaluation Tool
SkÀrmlÀsare (t.ex. NVDA eller VoiceOver).
💡 Extra Tips för Flutter-Webbappar
AnvÀnd flutter build web --target=lib/main_deferred.dart
FörbÀttrar code splitting.
Ladda Flutter asynkront
LĂ€gg till async i <script>-taggen:
html
Copy
<script src="/flutter_bootstrap.js" async></script>
AnvÀnd flutter_tex för text-rendering
Minskar beroendet av CanvasKit.
Override Flutter’s default fonts
AnvÀnd systemtypsnitt för snabbare laddning:
css
Copy
@font-face {
font-family: 'Roboto';
src: local('Roboto'), local('Roboto-Regular');
}
🎯 Sammanfattning: Vad du ska göra nu
Fixa de kritiska prestandaproblemen (HTML-renderare, GZIP, caching).
Fixa tillgÀnglighetsproblemen (user-scalable, alt-texter, lang).
Fixa SEO (meta description, robots.txt).
LÀgg till sÀkerhetsheaders (CSP).
Testa och iterera med Lighthouse.