Mobile Development 18 min read

Performance Optimization of Baidu App Landing Page: Hybrid Architecture, Backend Direct Output, Prefetch and Interception

This article details how Baidu App reduced the landing‑page first‑screen load from over 2600 ms to under 2000 ms by analyzing user feedback, instrumenting each loading stage of its Hybrid H5 solution, and applying a series of backend‑direct‑output, prefetch, WebView pre‑creation, lazy‑load and kernel‑level rendering optimizations together with code‑level fixes.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
Performance Optimization of Baidu App Landing Page: Hybrid Architecture, Backend Direct Output, Prefetch and Interception

Background

Baidu App began experimenting with a Feed flow in early 2016 and, after ten version iterations by late 2017, had a mature product shape. The landing page (called the "detail page") was identified as a performance bottleneck because long loading times severely hurt user experience.

Methodology

Through user feedback and QA testing the team discovered that the average time from click to first‑screen was about 3 seconds, causing many users to abandon the page. The optimization process included defining a first‑screen metric (with image or text as the completion point), instrumenting NA, kernel and H5 loading stages, generating performance reports (average and 80th‑percentile), analyzing bottlenecks, and validating improvements with A/B experiments.

Hybrid Solution Overview and Performance Bottlenecks

The original architecture used a Hybrid approach (half‑native, half‑Web) to satisfy cross‑platform and dynamic requirements. The loading pipeline was broken down into four stages:

NA component initialization – WebView creation (≈350 ms, first‑time ≈500 ms).

Hybrid initialization – template verification and parsing (≈170 ms).

Content load & render – JS fetches JSON, parses it, builds DOM and triggers kernel rendering (≈1400 ms).

Image load – network download, IO write, and kernel rendering (≈700 ms).

These stages summed to roughly 2600 ms for the 80th‑percentile first‑screen.

Baidu App Landing‑Page Optimization Scheme

1. CloudHybrid – Backend Direct Output

To eliminate the heavy H5‑only rendering path, the team introduced "CloudHybrid", which renders the first‑screen on the server (using Smarty) and streams a fully‑filled HTML page to the client. Dynamic information such as the cover image, font size and night mode is back‑filled on the client by replacing placeholder tokens before loading the URL.

Result: first‑screen latency dropped from ~2600 ms to <2000 ms.

2. Smart Prefetch – Early Network Requests

Static HTML generated by CloudHybrid is prefetched from CDN and cached locally so that a user click can load the page instantly from cache. The prefetch service supports configurable triggers (scroll stop, refresh, click) and priority‑based scheduling, with runtime flow‑control and cloud‑controlled enable/disable.

3. General Interception – Shared Cache & Parallel Requests

Image loading was further accelerated by intercepting image requests via shouldInterceptRequest , letting the native NA image downloader fetch and cache the resource, then feeding the data back to the WebView through WebResourceResponse . This decouples the client from the H5 code while sharing the image cache.

4. Additional Optimizations

WebView Pre‑creation : A pool of pre‑created WebViews (using MutableContextWrapper ) is maintained; when a landing page is needed, a cached WebView is retrieved and its base context is swapped, saving >200 ms of init time.

NA Component Lazy Loading : The comment component (NA) is delayed until the page finishes or the first‑screen paint completes, shaving 60‑100 ms.

Kernel Rendering Optimizations : A dedicated ParserThread parses HTML while the MainThread handles layout. When the layout height exceeds the screen height, rendering is triggered early, reducing first‑screen time by 100‑200 ms.

Pre‑load JS : After WebView pre‑creation, a small JS bundle is injected to perform only initialization, cutting another ~80 ms.

Code Fix for Activity Transition Rendering

/**
 * Allow activity transition animation to render the page normally
 */
private void setDrawDuringWindowsAnimating(View view) {
    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M || Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
        // Android N+ and <4.1 have no issue
        return;
    }
    // Android 4.2 needs special handling
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
        handleDispatchDoneAnimating(view);
        return;
    }
    try {
        // Android 4.3+ use reflection to enable drawing during window animation
        ViewParent rootParent = view.getRootView().getParent();
        Method method = rootParent.getClass().getDeclaredMethod("setDrawDuringWindowsAnimating", boolean.class);
        method.setAccessible(true);
        method.invoke(rootParent, true);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
/**
 * Android 4.2 can reflect handleDispatchDoneAnimating to solve the issue
 */
private void handleDispatchDoneAnimating(View paramView) {
    try {
        ViewParent localViewParent = paramView.getRootView().getParent();
        Class
localClass = localViewParent.getClass();
        Method localMethod = localClass.getDeclaredMethod("handleDispatchDoneAnimating");
        localMethod.setAccessible(true);
        localMethod.invoke(localViewParent);
    } catch (Exception localException) {
        localException.printStackTrace();
    }
}

WebView Pre‑creation Sample Code

/**
 * Create a WebView instance using application context
 */
@DebugTrace
public void prepareNewWebView() {
    if (mCachedWebViewStack.size() < CACHED_WEBVIEW_MAX_NUM) {
        mCachedWebViewStack.push(new WebView(new MutableContextWrapper(getAppContext())));
    }
}
/**
 * Acquire a suitable WebView from the cache
 * @param context activity context
 * @return WebView
 */
private WebView acquireWebViewInternal(Context context) {
    if (mCachedWebViewStack == null || mCachedWebViewStack.isEmpty()) {
        return new WebView(context);
    }
    WebView webView = mCachedWebViewStack.pop();
    // Replace the context of the pre‑created WebView
    MutableContextWrapper contextWrapper = (MutableContextWrapper) webView.getContext();
    contextWrapper.setBaseContext(context);
    return webView;
}

Balancing Traffic and Speed

Frequent prefetching wastes bandwidth; hit‑rate is >90 % but effective usage is only ~15 %. Strategies include compressing prefetch payloads (≈40 % size reduction for text‑image pages), reducing prefetch frequency, and applying AI‑driven prediction to only prefetch when user behavior suggests a high probability of navigation.

Conclusion & Outlook

The series of optimizations—early work (WebView pre‑creation, data prefetch), parallel execution (image direct‑out & interception), lightweight page generation (server‑side rendering, CSS/JS trimming), and simplification (using static output for low‑dynamic pages)—enabled Baidu App landing pages to achieve near‑instant (second‑level) opening. Future work includes supporting dynamic‑content update mechanisms and open‑sourcing the solution.

Mobile DevelopmentPerformance OptimizationAndroidWebViewHybridprefetchBackend Rendering
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

login 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.