MetaMask / metamask-extension

:globe_with_meridians: :electric_plug: The MetaMask browser extension enables browsing Ethereum blockchain enabled websites
https://metamask.io
Other
11.95k stars 4.89k forks source link

Optimize extension UI script loading #25721

Closed Gudahtt closed 1 month ago

Gudahtt commented 3 months ago

What is this about?

Our UI scripts are loaded in a strange manner. The initial page load just includes the load-app.js script, which itself loads and executes each script one at a time. Each script is downloaded, parsed, and run sequentially. We can speed up the page load by downloading and parsing them in parallel. We can preserve popup responsiveness by loading an initial lightweight popup page first that redirects to the full popup page.

Background

We wrote the load-app.js script to make the browser-action popup appear faster (see here for details: #20843). The popup doesn't begin rendering until the page load has completed (it seems to correspond with the load event). When we included scripts as regular <script> tags, parsing and executing these scripts would delay the load event by a significant amount of time, making the extension appear unresponsive to users when they clicked the popup.

By delaying the script imports, the load event was hit much faster. The load time was slightly increased but it appeared to be faster because users could see it loading, rather than seeing nothing.

Solution

By moving script tags back into the page, they can be downloaded and parsed in parallel by the browser, but still run one-at-a-time.

This would severely degrade the "perceived performance" of the popup because we'd be delaying the load event. We can overcome that by loading an initial "blank" popup page that hits the load event as fast as possible, then redirects to the real popup page. This does have a slight amount of overhead in loading and rendering this initial page before redirecting, but this overhead may be less than the time we're saving by optimizing the script loading in the real popup page.

For the fullscreen UI, this optimization is a strict improvement.

Scenario

No response

Design

No response

Technical Details

No response

Threat Modeling Framework

No response

Acceptance Criteria

Stakeholder review needed before the work gets merged

References

No response

Gudahtt commented 3 months ago

I began experimenting with this in the branch load-scripts-async. It appears successful so far, but the performance gains are not huge. I tried benchmarking it, but the variance between runs was far larger than the performance improvement. But it did seem faster on average, when I tested with 3 runs before and after.

Gudahtt commented 1 month ago

defer was used over async because async pauses HTML parsing, but defer does not. And because async does not guarantee the order in which scripts load, which we currently rely on.

async might be faster for some bundles if we find a way to create bundles that are not order-dependent. Further investigation needed there.

metamaskbot commented 1 month ago

Missing release label release-12.2.0 on issue. Adding release label release-12.2.0 on issue, as issue is linked to PR #26555 which has this release label.