Design and Performance Evaluation of an Offline Package Solution for H5 Pages in Mobile Apps
This article presents the design, implementation, and performance analysis of an offline‑package system that bundles H5 resources for WebView‑based mobile apps, detailing the configuration platform, webpack plugin, client SDK integration, and measured improvements in DNS, TCP, DOM‑Ready, and WebVitals metrics across various network conditions.
Background – H5 pages running inside a WebView are highly dependent on network conditions. An offline‑package approach packages HTML, JS, and CSS into a compressed bundle that the app downloads in advance, allowing the WebView to load resources locally and reduce white‑screen time.
The solution integrates a webpack plugin that creates the bundle, uploads it to a storage service (NOS), and registers the package on a configuration platform. The platform manages applications, versions, and update URLs, while the app server provides APIs for the client to fetch package lists and toggle offline‑package usage.
Overall Architecture – The frontend continues its normal development workflow; the plugin modifies the build process to generate a manifest.json , upload the zip to NOS, and submit a program.json to the configuration platform. The platform stores package metadata such as appId , name , version , refreshUrls , packages , and their dependencies.
Package Configuration Example
[
{
"appId": "离线包应用appId",
"name": "离线包应用名",
"version": "离线包应用版本",
"updateTime": "离线包应用配置项更新时间,可用于判断是否需要覆盖配置项",
"refreshUrls": ["www.lofter.com/mp/lofter878789/html/page1.html"],
"packages": [
{
"packageName": "package_1",
"loadingQuietly": true,
"dependencies": ["common trunk包"],
"urls": ["//www.lofter.com/market/page1.html", "//www.lofter/market/page2.html"],
"zipUrl": "https://xxx.nosdn.127.net/offline/xxxx.zip",
"md5": "xxxxxxxxxxxxxxxx"
},
{
"packageName": " package_2",
"dependencies": ["common trunk包"],
"urls": ["//www.lofter.com/market/page3.html", "//www.lofter/market/page4.html"],
"zipUrl": "https://xxx.nosdn.127.net/offline/xxxx.zip",
"md5": "xxxxxxxxxxxxxxxx"
},
{
"packageName": "common trunk包",
"loadingQuietly": true,
"zipUrl": "https://xxx.nosdn.127.net/offline/xxxx.zip",
"md5": "xxxxxxxxxxxxxxxx"
}
]
}
]Key fields include refreshUrls (trigger version checks), urls (resources to download), loadingQuietly (silent load flag), dependencies (package order), and zipUrl (the compressed resource bundle).
Offline‑Package Plugin – The webpack plugin runs before output generation, creates the manifest, uploads assets, and posts configuration to the platform. Example usage:
const OfflinePackage = require('lofter-mp-webpack-plugin');
const offlineEntry = getEntry();
module.exports = {
...
plugins: [
new HtmlWebpackPlugin(),
new OfflinePackage({
packageNameValue: 'test',
appId: 'lofter1',
uploadConfigUrl: 'http://www.lofter.com/mp/api/appVersion/add',
baseUrl: `//www.lofter.com/mp/lofter1/`,
cdnUrl: `//xx.cdn.com/mp/lofter1/`,
nosConfig,
ignoreFileTypes: ['txt', 'js.map'],
excludeFileName: ['page2'],
entry: offlineEntry,
extraManifest: {
"static/jquery.min.js": "//cdn.bootcss.com/jquery/2.2.4/jquery.min.js"
},
dividePackageConfig: [
{ loadingQuietly: true, entryFile: ['index'] },
{ loadingQuietly: false, entryFile: ['page1'] }
]
})
]
};The plugin must be placed after HtmlWebpackPlugin to access processed assets.
Client Implementation – Android uses an SDK that overrides shouldInterceptRequest to match URLs against the offline‑package list and serve local files. iOS uses NSURLProtocol to intercept WKWebView requests, with additional JavaScript hooks to preserve POST bodies and headers.
Logging tools on both platforms help verify which resources are intercepted.
Performance Evaluation – Using the “Lefu Market” H5 app, metrics such as DNS time, TCP time, DOM‑Ready, total load time, and WebVitals (FCP, LCP, CLS, FID) were collected before and after enabling offline packages. Results show significant reductions: DNS and TCP times dropped markedly, DOM‑Ready and total load times improved (up to 30% on Android), and FCP/LCP saw clear gains, especially under weak network conditions.
Detailed charts illustrate the percentage improvements and distribution of load times across different network simulations (Fast 3G, 4G, etc.).
Analysis – The main benefit comes from loading high‑priority resources (JS/CSS) locally, eliminating network latency. Even when the HTML is partially server‑rendered, the reduction in resource fetch time advances the rendering pipeline. Further gains are possible by adding more high‑priority assets to the offline bundle.
Conclusion – To maximize offline‑package effectiveness, all high‑priority external resources should be packaged, preventing them from blocking the main rendering thread. The approach reliably lowers DNS/TCP overhead and stabilizes resource loading across diverse network environments, leading to faster and more consistent user experiences.
LOFTER Tech Team
Technical sharing and discussion from NetEase LOFTER Tech Team
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.