Unifying JD’s JinxI Home Page Across H5, Mini‑Programs, and React‑Native with Taro

After the 2022 Double‑11 event, JD’s JinxI platform faced fragmented H5, mini‑program, and RN codebases, prompting a comprehensive redesign that standardized the tech stack with Taro, streamlined multi‑platform development, integrated custom build pipelines, and applied performance optimizations such as image handling, API aggregation, and caching.

WecTeam
WecTeam
WecTeam
Unifying JD’s JinxI Home Page Across H5, Mini‑Programs, and React‑Native with Taro

Background

Following the Double‑11 shopping festival, JD’s JinxI (formerly JD.com Pin‑Group) switched its primary entry to a WeChat mini‑program and successfully handled near‑billion traffic. However, the existing homepage suffered from multiple issues:

Different H5 pages for various channels caused high maintenance cost.

Inconsistent tech stack (traditional H5, native mini‑program, wqVue) increased complexity.

Separate build and release processes for H5, mini‑program, and RN hindered delivery efficiency.

These problems motivated a full redesign.

Redesign Goals (Frontend Perspective)

Upgrade and unify the tech stack.

Use a single codebase to support six business scenarios (WeChat entry, Hand‑Q entry, WeChat mini‑program, JD app, JinxI app, M‑site).

Introduce RN on the business side to strengthen app‑side capabilities.

Optimize performance and experience for lower‑tier market users.

Technical Selection

Given the diverse product forms (H5, mini‑program, independent app), the team chose the self‑developed multi‑platform solution Taro , which follows React syntax and can compile a single codebase to run on Web, React‑Native, WeChat/Alipay/ByteDance mini‑programs, quick‑apps, etc.

Taro is a multi‑platform development solution that adheres to React syntax. When business requires simultaneous implementation on multiple platforms, writing separate code for each is costly; Taro enables writing once and compiling to all targets. Using Taro, source code can be compiled into platform‑specific bundles for WeChat, Baidu, Alipay, ByteDance, QQ mini‑programs, quick‑apps, H5, React‑Native, and more.

The choice was driven by Taro’s maturity (used internally at JD 7FRESH, JD to Home, and externally by Taopiaopiao, Yue‑Sheng‑Shi) and the team’s prior experience with Taro‑based component libraries.

Development Record

Due to tight schedule, existing common libraries (request, reporting, navigation) were reused to reduce duplicated work. The following sections describe challenges and solutions for each platform.

H5

All pages depend on global header/footer components delivered via SSI. To preview locally, the SSI syntax in index.html must be resolved. A custom ssi-loader was added to the webpack chain in config/dev.js to fetch and replace virtual includes.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
  <title>京喜</title>
  <!--#include virtual="/sinclude/common/head_inc.shtml"-->
</head>
<body>
  <div id="m_common_header" style="display:none;"></div>
  <!--#include virtual="/sinclude/common/foot.shtml"-->
</body>
</html>

The webpack configuration added the loader:

module.exports = {
  h5: {
    webpackChain(chain, webpack) {
      chain.merge({
        module: {
          rule: {
            ssiLoader: {
              test: /\.html/,
              use: [
                { loader: 'html-loader' },
                { loader: 'ssi-loader', options: { locations: { include: 'https://wqs.jd.com' } } }
              ]
            }
          }
        }
      })
    }
  }
}

After local debugging, the build and release processes were integrated with gulp to produce directories compatible with the internal deployment platform.

Mini‑Program

The Taro mini‑program output was compiled into the existing native mini‑program project. The output directory was customized in config/index.js and the app file generation disabled to avoid overwriting existing files.

const config = {
  // custom output root
  outputRoot: process.argv[3] === 'weapp' ? '../.temp' : 'dist',
  weapp: {
    appOutput: false
  }
}

Base classes JDPage and JDComponent were injected via a gulp task that replaces import paths and wraps the code with the appropriate base class.

gulp.task('replace-base-component', () => replaceBaseComponent())

React‑Native (RN)

RN development leveraged the existing JDReact platform. The Taro RN output path was set to the JDReact bundle directory, enabling yarn run dev:rn to compile directly into the RN project.

rn: {
  outPath: '../jdreact-jsbundle-jdreactpingouindex'
}

Debugging used the official taro-native-shell and the React Native Debugger for a richer experience. Styling guidelines (fixed px, flex layout, scalePx2dp) and common pitfalls (empty string returns, border‑radius issues, transparent view clicks) were documented.

Cross‑Platform Development

JS Files

Common libraries were split per platform (e.g., request.h5.js, request.rn.js, request.weapp.js) and imported via a unified entry point. Taro’s environment variable process.env.TARO_ENV enabled conditional logic.

if (process.env.TARO_ENV === 'h5') {
  this.speedReport(8) // first screen render
} else if (process.env.TARO_ENV === 'weapp') {
  speed.mark(6).report()
} else if (process.env.TARO_ENV === 'rn') {
  speed.mark(7).report()
}

CSS Files

Platform‑specific styles were organized as index.base.scss (shared), index.rn.scss (RN), and index.scss (H5 & mini‑program). Conditional compilation directives ( #ifdef, #ifndef) allowed platform‑specific rules.

/* #ifndef RN */
box-shadow: 1px 1px 1px rgba(0,0,0,.1);
/* #endif */

Performance Optimization

Image Optimization

Using JD’s image service, images were resized, compressed (q70), and served in WebP when supported. Lazy‑load was enabled via the lazyload attribute.

API Aggregation

The homepage originally required over 20 backend APIs. An aggregated “direct‑out” API was created to combine these calls, reducing latency and simplifying front‑end code.

Cache‑First Strategy

Primary interface data is cached locally; subsequent visits load from cache first, providing instant rendering and a fallback when network fails.

High‑Performance Waterfall List

For the long, irregular waterfall list, a custom component rendered items only when they entered the viewport, drastically reducing memory usage on low‑end Android devices.

Conclusion

The project demonstrated that Taro can fully support large‑scale commercial multi‑platform projects. Although some extra effort was needed for platform‑specific adaptations, the overall maintenance cost was far lower than developing separate codebases. Ongoing performance tuning and user‑experience improvements remain a priority for the high‑traffic JinxI product.

References

Taro: https://github.com/NervJS/taro/

SSI: https://en.wikipedia.org/wiki/Server_Side_Includes

Taro‑native‑shell: https://github.com/NervJS/taro-native-shell

Remote Debugger: https://facebook.github.io/react-native/docs/debugging.html#chrome-developer-tools

React Native Debugger: https://github.com/jhen0409/react-native-debugger

Taro built‑in env variables: https://nervjs.github.io/taro/docs/envs.html

Taro high‑performance waterfall component (for RN): https://github.com/aNd1coder/taro-waterfall

frontendmulti-platformTaro
WecTeam
Written by

WecTeam

WecTeam (维C团) is the front‑end technology team of JD.com’s Jingxi business unit, focusing on front‑end engineering, web performance optimization, mini‑program and app development, serverless, multi‑platform reuse, and visual building.

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.