- 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
14 KiB
đš Kritiska Problem (Prioritet 1: Fixa Omedelbart) Dessa problem pĂ„verkar anvĂ€ndarupplevelsen mest och bör Ă„tgĂ€rdas först.
- 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 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
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
- 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
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">- 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
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.
- 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.
- 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 ),
- 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.
- 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, ),
- 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).
- 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.