Skip to content

perf: optimize Flutter web portfolio - #13

Merged
mentoster merged 9 commits into
masterfrom
perf/web-performance-icons
Jul 25, 2026
Merged

mentoster merged 9 commits into
masterfrom
perf/web-performance-icons

Conversation

@mentoster

@mentoster mentoster commented Jul 24, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • fixes instrument icon discovery on modern Flutter by using Flutter's AssetManifest API instead of legacy AssetManifest.json parsing
  • replaces the continuously animated triple plasma background with a static gradient composition
  • removes unused dependencies and reduces bundled image payload
  • modernizes Flutter web bootstrap and legacy service-worker cleanup
  • hardens nginx SPA/static routing so deep links work while missing assets return real 404s
  • removes all repository CI/CD GitHub Actions workflows; deploy/build remain manual

Performance

  • app image payload: ~22 MB -> ~11.55 MiB
  • build/web: ~63 MB -> ~53 MB
  • main.dart.js gzip: 980,589 -> 978,871 bytes
  • removed continuous triple PlasmaRenderer repaint workload

Verification

  • flutter analyze --no-fatal-infos: 0 errors, 0 warnings; 59 pre-existing info-level notices
  • flutter test: 3/3 passed
  • flutter build web --release: passed
  • nginx deep links return HTTP 200 and missing static assets return HTTP 404
  • no files remain under .github/workflows

Cloudflared and nginx1-nginx6 were not modified. nginx7 remains on host port 4077. This PR is intentionally left open and unmerged.

Summary by CodeRabbit

  • New Features

    • Added Docker/Nginx hosting support for the Flutter web portfolio, including SPA routing and compressed assets.
    • Improved web loading behavior by retiring legacy service workers and updating the startup experience.
    • Added support for loading instrument icons from custom asset bundles.
  • Improvements

    • Replaced the animated plasma background with a gradient-based design.
    • Updated project imagery and optimized certificate and diploma image loading.
    • Refreshed web publishing workflows and pinned the Flutter build environment.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The project updates Flutter tooling and dependencies, migrates widget APIs and rendering, improves asset loading and tests, and adds Flutter web bootstrap, Nginx, Docker Compose, and deployment configuration.

Changes

Flutter web modernization

Layer / File(s) Summary
Flutter toolchain baseline
.gitignore, pubspec.yaml
Dart constraints, dependencies, assets, and generated-file tracking are updated.
Widget and rendering migration
lib/app/ui/global_widgets/*, lib/app/ui/main_page/*, lib/app/ui/project_page/*, lib/app/ui/projects_page/*, lib/app/data/information_data/*
Animation, carousel, styling, image caching, layout, imports, and project rendering are adapted to updated APIs, while the animated background uses gradients instead of plasma renderers.
Asset loading and widget validation
lib/app/ui/main_page/sections/work_instruments/*, test/*
Instrument icons load through an optional asset bundle, with success and failure tests; the main widget test now verifies portfolio content.
Web delivery and hosting
web/*, deploy/nginx.conf, docker-compose.hosting.yml
The web entrypoint uses flutter_bootstrap.js, and Nginx/Docker Compose serve the built application with SPA fallback and static asset routing.

Estimated code review effort: 4 (Complex) | ~45 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and matches the PR’s main theme of optimizing the Flutter web portfolio.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/web-performance-icons

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
docker-compose.hosting.yml (1)

3-3: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Pin Nginx to an immutable digest.

nginx:latest makes deployments non-reproducible and can change server behavior without a code change. Pin a tested Nginx release by digest.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docker-compose.hosting.yml` at line 3, Update the Nginx image reference in
the compose configuration from the mutable nginx:latest tag to a tested Nginx
release pinned by its immutable image digest.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/fluttter_to_github_pages.yml:
- Line 14: Set persist-credentials to false on the actions/checkout steps in
.github/workflows/fluttter_to_github_pages.yml (line 14),
.github/workflows/dart_score.yml (line 9), and
.github/workflows/firebase-hosting-merge.yml (line 14), preserving each
workflow’s existing explicit deployment or analyzer credentials.

---

Nitpick comments:
In `@docker-compose.hosting.yml`:
- Line 3: Update the Nginx image reference in the compose configuration from the
mutable nginx:latest tag to a tested Nginx release pinned by its immutable image
digest.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 25ec5c35-e58d-4c67-afc5-3b464384f880

📥 Commits

Reviewing files that changed from the base of the PR and between 48ed182 and 82fa7be.

⛔ Files ignored due to path filters (1)
  • pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (24)
  • .github/workflows/dart_analyze.yml
  • .github/workflows/dart_score.yml
  • .github/workflows/firebase-hosting-merge.yml
  • .github/workflows/fluttter_to_github_pages.yml
  • .gitignore
  • deploy/nginx.conf
  • docker-compose.hosting.yml
  • lib/app/data/information_data/info_projects.dart
  • lib/app/ui/global_widgets/animated_background.dart
  • lib/app/ui/global_widgets/appbar.dart
  • lib/app/ui/global_widgets/projects_grid_widget.dart
  • lib/app/ui/main_page/main_page.dart
  • lib/app/ui/main_page/sections/certificates/widgets/certificate_widget.dart
  • lib/app/ui/main_page/sections/contact_me/widgets/social_network_button.dart
  • lib/app/ui/main_page/sections/diplomas/widgets/diploma_diploma_widget.dart
  • lib/app/ui/main_page/sections/top_section/widgets/left_text_column.dart
  • lib/app/ui/main_page/sections/work_instruments/widgets/small_icons_wrap_widget.dart
  • lib/app/ui/project_page/widgets/project_images.dart
  • lib/app/ui/projects_page/sections/top_section/widgets/projects_title.dart
  • pubspec.yaml
  • test/small_icons_wrap_widget_test.dart
  • test/widget_test.dart
  • web/flutter_bootstrap.js
  • web/index.html
💤 Files with no reviewable changes (2)
  • lib/app/ui/global_widgets/projects_grid_widget.dart
  • .gitignore

Comment thread .github/workflows/fluttter_to_github_pages.yml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/flutter_bootstrap.js`:
- Around line 10-25: Make the cleanup marker access in the service-worker
cleanup IIFE best-effort: guard both sessionStorage.getItem and
sessionStorage.setItem in try/catch so storage exceptions do not abort startup
or prevent _flutter.loader.load(). Preserve the existing cleanup and marker
behavior when storage is available, using cleanupKey and the current cleanup
flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 97adb441-acb0-4f48-a9ac-6c7200b9f466

📥 Commits

Reviewing files that changed from the base of the PR and between 82fa7be and 8672ac0.

⛔ Files ignored due to path filters (1)
  • pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • .github/workflows/dart_analyze.yml
  • .github/workflows/dart_score.yml
  • .github/workflows/firebase-hosting-merge.yml
  • .github/workflows/fluttter_to_github_pages.yml
  • pubspec.yaml
  • web/flutter_bootstrap.js
💤 Files with no reviewable changes (4)
  • .github/workflows/firebase-hosting-merge.yml
  • .github/workflows/fluttter_to_github_pages.yml
  • .github/workflows/dart_score.yml
  • .github/workflows/dart_analyze.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • pubspec.yaml

Comment thread web/flutter_bootstrap.js
Comment on lines +10 to +25
if (sessionStorage.getItem(cleanupKey) === 'done') {
return true;
}

const registrations = await navigator.serviceWorker.getRegistrations();
const currentUrl = window.location.href;
let removedController = false;

for (const registration of registrations) {
if (currentUrl.startsWith(registration.scope)) {
const removed = await registration.unregister();
removedController = removedController || removed;
}
}

sessionStorage.setItem(cleanupKey, 'done');

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Repository files matching flutter_bootstrap.js:"
fd -a 'flutter_bootstrap\.js$' . | sed 's#^\./##'

file="$(fd 'flutter_bootstrap\.js$' . | head -n 1 || true)"
if [ -n "${file:-}" ]; then
  echo
  echo "Line count:"
  wc -l "$file"
  echo
  echo "Relevant source:"
  cat -n "$file" | sed -n '1,120p'
  echo
  echo "Search for retireLegacyServiceWorker / flutter.loader.load:"
  rg -n "retireLegacyServiceWorker|_flutter\.loader\.load|sessionStorage|serviceWorker" "$file" || true
fi

echo
echo "Check package/index references (if any) to web/flutter_bootstrap.js:"
rg -n 'flutter_bootstrap\.js|retireLegacyServiceWorker|_flutter\.loader\.load' . -g '!build/**' -g '!dist/**' || true

Repository: mentoster/portfolio_flutter_web

Length of output: 3008


🌐 Web query:

MDN ServiceWorkerContainer unregister navigator.serviceWorker.controller

💡 Result:

To unregister a service worker, you must call the unregister method on a ServiceWorkerRegistration object, not on the ServiceWorkerContainer or the navigator.serviceWorker.controller property [1][2]. The navigator.serviceWorker.controller property is a read-only reference to the active ServiceWorker object controlling the current page [3]. It does not have an unregister method [4][3]. To programmatically unregister a service worker, follow these steps: 1. Retrieve the registration(s): Use navigator.serviceWorker.getRegistrations to get a list of all active registrations for the current origin [5][6]. 2. Call unregister: Iterate through the returned registrations and call the unregister method on each one [5][6]. Example code: if ('serviceWorker' in navigator) { navigator.serviceWorker.getRegistrations.then((registrations) => { for (const registration of registrations) { registration.unregister.then((boolean) => { if (boolean) { console.log('Service worker unregistered successfully.'); } }); } }); } The unregister method returns a Promise that resolves to true if the service worker was unregistered, or false if no registration was found [1]. Note that unregistering a service worker does not immediately stop it; it will finish any ongoing operations before it is removed [1][2]. Additionally, the change will not affect the current page until it is reloaded [5].

Citations:


Do not let storage access block application startup.

sessionStorage.getItem or setItem can throw when browser storage is unavailable or blocked. Since that exception is not caught before the async IIFE reaches _flutter.loader.load(), the app can remain stuck on the loading screen. Treat the cleanup marker as best-effort: wrap storage access and continue bootstrapping if it fails.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/flutter_bootstrap.js` around lines 10 - 25, Make the cleanup marker
access in the service-worker cleanup IIFE best-effort: guard both
sessionStorage.getItem and sessionStorage.setItem in try/catch so storage
exceptions do not abort startup or prevent _flutter.loader.load(). Preserve the
existing cleanup and marker behavior when storage is available, using cleanupKey
and the current cleanup flow.

@mentoster
mentoster merged commit a95b769 into master Jul 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant