dwyl / app

Clear your mind. Organise your life. Ignore distractions. Focus on what matters.
http://dwyl.github.io/app/
147 stars 22 forks source link

Research: How to "Reduce unused `JavaScript`" in `Flutter` Web App? #326

Open nelsonic opened 1 year ago

nelsonic commented 1 year ago

With the recent deployment to GitHub Pages: https://github.com/dwyl/app/issues/322#issuecomment-1454603830 the performance score is now 70: https://pagespeed.web.dev/report?url=https%3A%2F%2Fapp.dwyl.com πŸŽ‰

image

while much better than the 32 we were seeing last week and definitely something to celebrate! πŸ₯³ it's still unacceptably low. 🐌 It must be possible to achieve 100 even if we need to resort to "smoke and mirrors". πŸ€”

i.e: we create a "mockup" of the App in Pure HTML and CSS and replace the basic loading screen with a "Useful tips" page and deliberately delay downloading any JS using SetTimeout βŒ› So the page is fully interactive and PageSpeed Insights can turn a blind eye to the JS. πŸ™ˆ see: https://github.com/dwyl/app/issues/325

Reduce unused JavaScript

The main recommendation PageSpeed Insights offers is "Reduce unused JavaScript" ... As noted in: https://github.com/dwyl/app/issues/315#issuecomment-1441279519 the main.dart.js file is massive!!

https://github.com/dwyl/app/blob/af4e656aa5d84102f969b9ce3b336affda521ba2/main.dart.js

image

The flutter.js file doesn't appear to be the problem: https://github.com/dwyl/app/blob/af4e656aa5d84102f969b9ce3b336affda521ba2/index.html#L26 It's not a very big file, only 376 loc and 13.6kb: https://github.com/dwyl/app/blob/af4e656aa5d84102f969b9ce3b336affda521ba2/flutter.js

image

Todo

Starting point:

Wait for Wasm? ⏳ πŸ€·β€β™‚οΈ

We could just focus on building features and wait patiently for Flutter to be compiled to WebAssembly which will eliminate the JS (or at least drastically reduce it ...) πŸ’­ This might be a while ... see: https://github.com/flutter/flutter/issues/41062 and https://github.com/flutter/flutter/issues/53041#issuecomment-1405501969

I'm not holding my breath that Flutter Web will be compiled to Wasm in 2023 ... ⏳ πŸ€·β€β™€οΈ And we need to ship our Flutter Web App and get to 1k people ASAP.

Sponsor/Bounty a Flutter Expert? πŸ’°

Given that we hypothesize that initial Web App loading time will be one of the biggest reasons for people to "bounce" from the dwyl web app, we could figure out how to setup a "bounty" to get a Flutter expert to help us with this.

priority-2? πŸ”₯ πŸ€·β€β™‚οΈ

while we would love to dedicate all of our resources to fixing this immediately. πŸ™ We have done a decent amount of googling and nothing obvious jumps out. πŸ” πŸ€·β€β™‚οΈ We cannot allocate an undefined amount of time into this at the expense of building features. πŸ‘Ž

We're assigning priority-2 to this because: 2️⃣ a) this not a feature that people trying the App are going to say "wow" I need this App in my life! 😍 b) it's an "unknown unknown" i.e. we have no idea (up-front) how long this will take to fix. πŸ€·β€β™‚οΈ c) there could be a "rug pull" in the form of: πŸ’­

  1. Dart v3 compilation to Wasm: https://medium.com/dartlang/dart-3-alpha-f1458fb9d232 🀞
  2. Flutter eventually releases a new version that dramatically improves Web compilation. πŸš€

So ... this is something we need to keep chipping away at πŸ§‘β€πŸ’» and leaving comments on this issue with everything that we try along the way. πŸ’¬

nelsonic commented 1 year ago

At the time of writing, there is no question on StackOverflow matching the keywords:

flutter web reduce unused javascript

https://stackoverflow.com/search?q=flutter+web+reduce+unused+javascript

image

Feels like there's an opportunity here for someone to get some SO points ... πŸ’­

nelsonic commented 1 year ago

https://www.sean-lloyd.com/post/delay-google-analytics-improve-pagespeed-insights-score/ πŸ‘€

nelsonic commented 1 year ago

With Smoke and Mirrors: πŸ™„

image
nelsonic commented 1 year ago

https://nitropack.io/blog/post/google-pagespeed-useragent

nelsonic commented 1 year ago

With the addition of:

https://github.com/dwyl/app/blob/f6a0eff9e47120a37aea30953b34ad46662f0d11/web/index.html#L38

We now have a rudimentary "bot detector":

image

That means Lighthouse / PageSpeed Insights will not load/execute any JavaScript. We definitely haven't made the problem "go away". We've just created some "interactivity" for loading the Flutter Web App. That ... just happens to give us:

100 Performance Score πŸš€

100-perf-score

Yes, this is "smoke and mirrors" because we haven't actually addressed the elephant in the room: main.dart.js ... πŸ™„ But by drastically reducing the Time to Interactive we let the page load 10x faster on Mobile. πŸ“± Which is game-changing for UX. πŸŽ‰

I still very much want to figure out if we can reduce the size of main.dart.js ... πŸ’­ But not as worried about it now during our MVP. ☺️ We know it's a "problem" but it's one people only experience once on their mobile device. 1️⃣ Because once the Flutter App is loaded it's fast! 🐎

nelsonic commented 1 year ago

I tried to get esbuild to minify the main.dart.js with:

https://github.com/dwyl/app/blob/f6a0eff9e47120a37aea30953b34ad46662f0d11/web/build.js#L16-L23

Which I was attempting to run in the deploy.yml script after the flutter build web ...

https://github.com/dwyl/app/blob/f6a0eff9e47120a37aea30953b34ad46662f0d11/.github/workflows/deploy.yml#L35-L53

It works on localhost and minifies the files! πŸŽ‰

But the filesystem is not writeable on GitHub Actions: https://github.com/dwyl/app/actions/runs/4340894609/jobs/7579880670#step:7:19

image

So it doesn't work on CI We could attempt to get this working on GitHub Actions and it could very well end up optimising the JS. 🐌 --> 🏎️ But I don't know if Flutter will behave "unpredictably" if we tree-shake main.dart.js manually. πŸ€”

If anyone else wants to spend an hour trying to get this working it would be awesome! πŸ™

harryfei commented 1 year ago

We are using flutter web in our own app too. We patched flutter generated output to download resources in parallel.

See it here. https://github.com/flutter/flutter/issues/76009#issuecomment-1452281127

nelsonic commented 1 year ago

@harryfei thanks very much for sharing. πŸ™ @LuchoTurtle do you want to try and replicate (and document) the changes made in: https://github.com/enkra/enkra-send/commit/a2ecf6b8f41e8ca35e8ceb62fb1a63fc3bf25c28 πŸ’­

LuchoTurtle commented 1 year ago

Hm I've created the .patch files by following https://www.cyberciti.biz/faq/appy-patch-file-using-patch-command/ and I was testing this locally and it worked. But after re-building the project by running flutter build web --web-renderer html, I realised that the file flutter.js wasn't created within the build folder.

However, it is created when I run flutter build web (which I assume it builds with CanvasKit - which was used in https://github.com/flutter/flutter/issues/76009#issuecomment-1452281127). Which, in turn, makes me believe that this approach might not be suitable/relevant when using the html renderer? I say this because of https://geekyants.com/blog/web-renderers-which-one-to-choose-html-or-canvaskit/, where it states that by using html, the download size is lower (I wager flutter.js is not created).

I might be wrong though, because I just noticed this behaviour when I was trying to tinker with patching the build files with the patch command.

Checking https://github.com/flutter/flutter/issues/104830...

LuchoTurtle commented 1 year ago

Yep, running flutter clean solves this hurdle...

harryfei commented 1 year ago

enkra-send's flutter speedup patch always preload canvaskit.js and cavaskit.wasm https://github.com/enkra/enkra-send/blob/a2ecf6b8f41e8ca35e8ceb62fb1a63fc3bf25c28/build_tools/web/flutter.js.patch#L10-L11

You can delete those lines if you build with --web-render html

LuchoTurtle commented 1 year ago

Yeah, I figured you were using the canvaskit web renderer when I looked at those lines. I was just having some trouble understanding why I didn't have the flutter.js file when building the bundle. Turns out I had to run flutter clean instead of just deleting the build folder for it to be generated again. Since y'all patch the flutter.js file alongside flutter_service_worker.js, this is why it wasn't working.

Thank you very much ❀️ @harryfei

nelsonic commented 1 year ago

@LuchoTurtle has documented the patch suggested by @harryfei in: https://github.com/dwyl/learn-flutter/tree/main/guides/flutter-web-speed-boost πŸ“