Frontend Development 19 min read

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.

JD Retail Technology
JD Retail Technology
JD Retail Technology
Front‑End Optimization Strategies for JD PLUS Membership Project

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 --save

Configuration 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') === 0

If 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

frontendperformanceimage optimizationBabelCachingWebpackPWA
JD Retail Technology
Written by

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.

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.