Frontend Development 25 min read

Technical Case Study of JD Smart Procurement App: Frontend Architecture, Component Library, Build Tools, and Optimization

This article presents a comprehensive technical case study of the JD Smart Procurement mobile app, detailing its front‑end architecture based on Vue, the use of the NutUI component library, TypeScript integration, request handling with Axios, build tooling with Gaea, multi‑page Webpack configuration, performance optimizations, and solutions to various development challenges.

JD Retail Technology
JD Retail Technology
JD Retail Technology
Technical Case Study of JD Smart Procurement App: Frontend Architecture, Component Library, Build Tools, and Optimization

The JD Smart Procurement App is an enterprise‑focused mobile procurement platform built on JD's mobile technology, aiming to digitize procurement across multiple industries such as finance, telecom, transportation, energy, and more.

Two major procurement pain points are addressed: mobile‑centric purchasing and employee‑benefit/channel‑reward distribution, both solved through a collaborative online procurement workflow.

Front‑end Architecture

The project adopts Vue as the core framework and utilizes JD's internally developed mobile component library NutUI (2.0+). Key components highlighted include:

Address – a four‑level address selector used in shopping‑type flows.

Dialog – supports both tag‑style and function‑style usage. Example usage:

this.$dialog({
  title: "是否确定提交",
  content: "采购人将第一时间看到您的提报,在下单之前可撤回重新修改"
});
<nut-dialog title="清单Excel将发送至以下邮箱">
    <input type="text" placeholder="请输入邮箱地址" class="inputemail"/>
</nut-dialog>

Function‑style dialog with HTML content:

_this.$dialog({
  title: "清单Excel将发送至以下邮箱",
  content: "<input type=\"text\" placeholder=\"请输入邮箱地址\" class=\"inputemail\"/>"
});

Retrieving the input value (currently using DOM query):

let email = (document.querySelector('.inputemail') as any).value

Stepper – a numeric stepper component used in cart pages, with methods such as add, reduce, change, focus, blur.

TypeScript Integration

The project combines Vue, Vuex, and TypeScript. Vue‑property‑decorator is used for class‑style components:

import { Vue, Component, Prop } from 'vue-property-decorator'
@Component({
  components: {}
})
export default class ReportItem extends Vue {
  @Prop({ type: Object, required: true, default: {} }) itemData!: object
}

Vuex is typed via the vuex‑class helper:

import { createDecorator } from 'vue-class-component';
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex';
export var State = createBindingHelper('computed', mapState);
// ... helper implementation ...
import { State, Mutation } from 'vuex-class'
export default class ReportList extends Vue {
  @State scrollTop
  @Mutation saveTop
}

Network Request Layer

Axios is the preferred HTTP client. A typed request wrapper is defined:

export interface ReqOptions {
  uri?: string;
  query?: object | null;
  data?: { [key: string]: any };
}
export interface ResOptions {
  code: number | string;
  message: string;
  data: { [key: string]: any };
}
class Request {
  static instance: Request;
  request: AxiosInstance;
  cancel: Canceler | null;
  methods = ['get', 'post'];
  curPath: string = '';
  constructor(options: AxiosRequestConfig) {
    this.request = axios.create(options);
    this.cancel = null;
    this.curPath = options.baseURL || '';
    this.methods.forEach(method => {
      this[method] = (params: ReqOptions) => this.getRequest(method, params);
    });
    this.initInterceptors();
  }
  // ... initInterceptors, getRequest, getInstance ...
}
export let api = Request.getInstance();
const res = await this.$api.get({ uri: reportTab });

Global Vue typings are extended in shime-global.d.ts to expose $api , $router , etc.

Performance Optimizations

Lazy‑load images using a custom directive or the vue-lazyload plugin.

Skeleton screens for page placeholders before data loads.

Gaea build tool (Node.js + Webpack) with Happypack, progress‑bar, and notifier plugins to speed up builds.

Code splitting via dynamic import() for route‑level components.

Multi‑page Webpack configuration with separate entry points and html-webpack-plugin instances.

Keep‑alive with scroll position caching to preserve list scroll state.

Global navigation guard to toggle keepAlive per route.

iOS low‑version keyboard handling by listening to focusout and resetting scroll.

Header gradient effect on scroll, later simplified to a solid color change after a threshold.

Conclusion

The article demonstrates a full‑stack front‑end solution for a mobile procurement system, covering component reuse, TypeScript safety, request abstraction, build efficiency, and UI/UX refinements, while sharing practical lessons learned throughout the development process.

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