Optimizing Static Resource Loading for Meituan Scan-to-Pay with ThunderJS and Build Service

Meituan’s Scan‑to‑Pay H5 app uses ThunderJS and a dedicated Build Service to deliver character‑level incremental JavaScript updates, switching to Myers’ algorithm, isolating computation in a Mixer service, caching results, and adding timeout recovery, which cut data transfer up to 99%, reduced 90th‑percentile latency from 5.8 s to 90 ms, and raised success rates above 99%.

Meituan Technology Team
Meituan Technology Team
Meituan Technology Team
Optimizing Static Resource Loading for Meituan Scan-to-Pay with ThunderJS and Build Service

Initial Solution

Meituan Financial Smart Payment’s Scan-to-Pay is an H5‑based payment product for end‑users. After a purchase, users can scan a QR code with various apps (Meituan, Dianping, WeChat, Alipay, Meituan Wallet) to complete payment and leave feedback. The service handles tens of millions of daily page views.

Because merchants are often located in dense indoor spaces (shopping malls, office buildings) with poor network conditions, the team adopted the internally built module loader ThunderJS. ThunderJS performs character‑level incremental updates to reduce file transfer size, save bandwidth, and improve page load success and speed. The incremental calculation is powered by Meituan’s static‑resource hosting solution, Build Service.

ThunderJS Workflow

ThunderJS stores JS resources and version information in LocalStorage. On page load it compares the online version with the local version to decide whether an update is needed. If an update is required, it issues a diff‑merge request, receives a patch, and applies it locally. If no update is needed, the cached resources are executed directly. When a diff request fails, ThunderJS falls back to loading individual files.

Update Decision Rules

The file name exists both online and locally.

The file’s version is identical online and locally.

The file is present in LocalStorage.

Diff Merge Request & Patch Diff

A diff‑merge request returns a JSON structure that describes how to reconstruct the latest file from the original file and a series of patches. The JSON specifies the offset, length, and inserted characters for each patch.

Build Service Workflow

Build Service is Meituan’s static‑resource hosting platform. It deploys, processes, and distributes resources via CDN. When a request misses the CDN cache, it is routed back to the origin server, processed, and then served through the CDN. Incremental computation is performed as a resource‑processing task on the origin.

Choosing the Incremental Algorithm

The initial implementation used an edit‑distance algorithm with O(N²) complexity, which was too slow for large texts. Build Service switched to Myers’ incremental algorithm, reducing the complexity to O(N·D) (N = text length, D = difference length). In typical web iterations D is small, making the algorithm close to linear time.

Initial Effects

Compared with full‑file requests, incremental updates reduced transferred data by up to 99% and cut the number of HTTP requests by about 95%.

Business Growth and Computation Bottlenecks

By April 2017 the project reached millions of PVs. The modular design led to an ever‑increasing number of files; a single merge request could contain more than 30 files. Incremental computation across many version combinations caused the Build Service to hit a 3‑second timeout threshold, with failure rates exceeding 50%.

Build Service Optimization Strategies

Service Splitting & Isolation

The original Build Service shared a common cluster with other tasks (compression, reference calculation). Incremental computation monopolized CPU resources, causing latency for other jobs. The team extracted the merge and incremental computation into a dedicated “Mixer” service, isolating it from the rest of the platform.

Persistent Computation Cache

Mixer now caches the output of each file’s computation task. Subsequent merge requests can reuse cached fragments, reducing redundant work. After deployment, Mixer’s success rate stabilized at 100% and each patch was generated within 50 ms.

Timeout Auto‑Restart

When a diff computation became slow (worst‑case O(N²)), the Mixer process would be killed and automatically restarted by PM2. The failed request would fall back to single‑file loading, allowing fast computations to proceed while the slow one was retried.

ThunderJS Optimization Strategies

Limit Merged File Count

The team capped the number of files per merge request to 10 (instead of unlimited). This split a 30‑file merge into three parallel requests, easing memory pressure and reducing timeouts.

Degradation Mechanism

If a merge request timed out, ThunderJS switched from creating script elements to using XHR to fetch individual files and store them in LocalStorage, improving cache reuse during network degradation.

Weak‑Network Prioritization

Network types are classified as WiFi, 4G, 3G, 2G, unknown. 2G and unknown are treated as weak networks (≈10% of users). For these users ThunderJS prefers cached files; if a cache miss occurs it falls back to single‑file requests.

Fundamental Solution to the Bottleneck

Asynchronous Computation Service (Brain)

The architecture was redesigned to separate computation (Brain service) from distribution. Brain stores a unique trace ID for each computation in MySQL and ensures only one node processes a given trace. Other nodes can retrieve the result directly, enabling horizontal scaling and eliminating resource contention between computation and serving processes.

After launch, Mixer no longer performed computation, availability rose to 99.99%, 90th‑percentile latency dropped from 5800 ms to 90 ms, and diff‑merge success increased by at least 50%.

Pre‑warm Strategy Before Release

Because some computation time is unavoidable, the team pre‑computes diffs for upcoming versions. By pre‑warming the last 5 versions, timeout rates fell to 1.5%; pre‑warming 10 versions reduced them to 1.1%.

Summary

ThunderJS’s incremental update scheme has delivered significant traffic and latency savings for Scan‑to‑Pay. Approximately 90% of requests come from mobile networks; daily bandwidth savings reach 49.37 GB, with incremental updates alone saving 33.41 GB per day.

Recruitment

The Meituan Financial Smart Payment front‑end team is hiring senior front‑end engineers and technical experts. Interested candidates can contact via the team’s public account, WeChat (yoyo779269), or email ([email protected]).

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Front-endPerformance OptimizationWeb PerformanceStatic Resourcesmodule loaderBuild Service
Meituan Technology Team
Written by

Meituan Technology Team

Over 10,000 engineers powering China’s leading lifestyle services e‑commerce platform. Supporting hundreds of millions of consumers, millions of merchants across 2,000+ industries. This is the public channel for the tech teams behind Meituan, Dianping, Meituan Waimai, Meituan Select, and related services.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.