Front‑End Optimization Strategies for JD PLUS Membership Project
This article details the front‑end performance improvements applied to JD's PLUS membership platform, covering architecture migration to Gaea 4.0, on‑demand Babel polyfill loading, PWA caching, request sequencing, skeleton screens, and modern image formats such as WebP and DPG.
Author Introduction FransLee is a front‑end engineer in JD.com’s User Experience Design department. He joined JD in 2016 and has been responsible for the architecture and development of the PLUS membership project, accumulating extensive experience in front‑end architecture, componentization, and technical breakthroughs.
The JD PLUS membership project is China’s first paid e‑commerce membership service, now serving over ten million users. The project features a massive number of requirements, frequent iterations, and a constantly changing product‑manager team, making performance, stability, and maintainability critical concerns.
1. Architecture Upgrade
The project is migrating to the Gaea 4.0 scaffold, a Vue‑based SPA built on Webpack 4. The upgrade includes:
Webpack upgraded to 4.0 (scope hoisting, smaller production bundles, faster incremental builds).
Babel upgraded to 7.0 (smart polyfill on‑demand).
Vue‑loader upgraded to 15.
Rewritten upload plugin for faster, more stable test‑server uploads.
Integration of the proprietary Carefree solution for cross‑LAN device debugging.
Adoption of the NutUI component library with on‑demand loading.
Integration of the internal SMOCK data‑mock tool based on Swagger.
Support for automatic skeleton‑screen generation.
Full PWA support.
The main goals are to leverage Webpack 4’s performance improvements, enable smarter polyfill handling with Babel 7, and lay the groundwork for PWA and skeleton‑screen features.
2. Babel Polyfill On‑Demand Loading
Modern web apps compile high‑level JavaScript to older syntax during build time, but new APIs (Promise, Set, etc.) still require polyfills. Traditional babel‑polyfill bundles all polyfills (~80‑90 KB). The project switches to @babel/preset‑env with useBuiltIns set to usage , which injects only the polyfills actually used per file.
Installation command:
npm install @babel/polyfill --saveConfiguration example (in .babelrc or .browserslistrc ):
{
"presets": [["@babel/preset-env", {"useBuiltIns": "usage", "corejs": 3}]]
}When useBuiltIns is entry , Babel replaces a single import "@babel/polyfill" with the full bundle. When set to usage , Babel analyses each file and adds only the necessary imports, e.g.:
import "core-js/modules/es7.string.pad-start";
import "core-js/modules/es7.string.pad-end";In practice this reduced the final minified bundle by over 60 KB while avoiding global variable pollution.
3. Persistent Cache (PWA)
The project adopts PWA offline caching for static assets to accelerate page loads, while deliberately avoiding full‑page offline support because the PLUS pages are frequently updated. A version‑ed URL strategy is used: when a file changes, its URL query/version string is updated, forcing the browser to fetch the new file while other cached assets remain untouched.
Stable third‑party libraries (Vue, plugins) are compiled into a separate vendor.dll.js using Webpack’s DllPlugin and DllReferencePlugin . This DLL bundle receives a stable hash, enabling long‑term caching, while the business bundle app.js is versioned per release.
4. Request Optimization
The SPA relies on many dependent API calls (user status, floor configuration, etc.), which caused serial requests and delayed first‑screen rendering. The team introduced a server‑side template that injects essential user and layout data into the initial HTML, allowing the client to render the first screen immediately and then fire dependent requests in parallel.
Performance graphs (original vs. optimized) show a significant reduction in time‑to‑first‑paint and overall page load.
5. Skeleton Screen
A skeleton screen is generated using a custom Webpack plugin @nutui/draw-page-structure that leverages Puppeteer to capture a pure‑DOM placeholder. This lightweight DOM skeleton replaces heavyweight image or canvas placeholders, improving perceived performance.
6. Image Formats
The team switched many assets to WebP, achieving up to 90% size reduction (e.g., a 35 KB PNG became a 4 KB WebP) with negligible visual loss. Compatibility issues remain on Safari/iOS, so a fallback strategy is employed.
Additionally, JD’s internal DPG format (a JPEG‑compatible lossy compression) is evaluated. DPG offers ~50% size reduction while being supported across all browsers because it remains a JPEG container.
Runtime detection code for WebP support:
document.createElement('canvas').toDataURL('image/webp').indexOf('data:image/webp') === 0If supported, a webp class is added to body and the result is cached in localStorage for subsequent visits.
7. Further Reading
References:
[1] Gaea CLI
[2] Carefree debugging solution
[3] NutUI component library
[4] SMOCK mock tool
[5] @nutui/draw-page-structure plugin
JD Retail Technology
Official platform of JD Retail Technology, delivering insightful R&D news and a deep look into the lives and work of technologists.
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.