Frontend Development 17 min read

Cross‑Platform Development of Qingju Bike Mini‑Program Using the Chameleon Framework

The case study shows how Qingju Bike’s high‑traffic bike‑sharing mini‑program was built with the Chameleon cross‑platform framework, delivering consistent UI across WeChat, Alipay and other entry points, meeting strict performance and security demands while cutting development time by half and simplifying maintenance.

Didi Tech
Didi Tech
Didi Tech
Cross‑Platform Development of Qingju Bike Mini‑Program Using the Chameleon Framework

This article presents a comprehensive case study of building the Qingju Bike mini‑program with the Chameleon cross‑platform framework. It outlines the rapid growth of mini‑programs, the high daily active user count of Qingju Bike, and the strict performance, stability, and security requirements that drive the selection of a suitable framework.

Background

Mini‑programs have surpassed one million applications and serve over 200 industries, with daily active users reaching 200 million. Qingju Bike, a high‑traffic bike‑sharing mini‑program, needs to support multiple entry points (WeChat, Alipay, Amap, etc.) while maintaining consistent user experience across platforms.

Framework Expectations

Highly consistent UI across all platforms without duplicated development effort.

Easy extensibility for platform‑specific customizations.

Strong engineering support (modularization, automated builds, testing).

Minimal code changes when integrating the framework.

Strict performance constraints on package size, loading, rendering, and response times.

Cross‑Platform Framework – Chameleon

Chameleon provides a DSL layer on top of each platform’s runtime, handling routing, lifecycle, component abstraction, data binding, and style rendering. It uses Webpack‑based tooling (chameleon‑tools) for compilation, and chameleon‑UI / chameleon‑API to smooth out API differences.

<script cml-type="interface">
  // Define input parameters
  type RESObject = {
    code: string,
    errMsg: string
  }
  type done = (res: RESObject) => Void

  interface MethodsInterface {
    login(timeout: String, opt: done): Void
  }
</script>
<script cml-type="wx">
  class Login implements LoginInterface {
    login (timeout, opt) {
      wx.login(timeout, code => done({code: ''12', errMsg: '成功'}));
    }
  }
  export default new Login()
</script>
<script cml-type="alipay">
  class Login implements LoginInterface {
    login (timeout, opt) {
      my.getAuthCode(timeout, code => done({code: ''12', errMsg: '成功'}));
    }
  }
  export default new Login()
</script>

The above demonstrates how a single interface can be implemented differently for WeChat and Alipay, enabling seamless multi‑platform login.

Business Architecture

The Qingju Bike flow includes login, authentication, electronic fence, order creation, unlocking, riding, and payment, spanning more than 30 pages. By abstracting platform‑specific SDKs and using a unified store, the team reduces duplicated code and simplifies maintenance.

import cml from "chameleon-api";

cml.get({
  url: '/api/getUserInfo'
})
.then(res => {
  // ...handle success
  cml.setStorage('user', ...res)
}, err => {
  cml.showToast({
    message: JSON.stringify(err),
    duration: 2000
  })
});

Configuration of API prefixes for dev and production environments is handled centrally:

const testApiPrefix = 'http://test.api.com';
const apiPrefix = 'http://prod.api.com';

cml.config.merge({
  wx: {
    dev: { apiPrefix: testApiPrefix },
    build: { apiPrefix }
  }
});

Engineering Practices

Command line shortcuts: cml dev (compile all), cml wx dev (compile WeChat), cml build (production build).

Data mocking via /mock/api/ directory for local development.

State management using chameleon-store , analogous to Vuex, with modules such as user , location , and bicycle .

import createStore from 'chameleon-store';
import user from './user';
import location from './location';

const store = createStore({
  modules: { user, location, bicycle }
});
export default store;

Component communication follows a parent‑child pattern with event bus handling. Example of an ActionCard component:

<template>
  <view class="action-card">
    <view class="{{'content '+(remindActive && 'bigSmall')}}">
      // ...
    </view>
  </view>
</template>

<script>
class ActionCard {
  mounted () {
    EventBus.on(REMIND_CARD, ({index}) => {
      if (index === this.index) this.remind();
    });
  }
  methods = {
    callback (e) {
      EventBus.emit(ACTION_CARD, {index: this.index});
    }
  }
}
export default new ActionCard();
</script>

Performance improvements stem from an array‑diff algorithm that only transmits changed parts of the virtual DOM, reducing the load on the WebView and JS engine. Package size remains stable at around 1.2 MB after compression.

Conclusion

Adopting Chameleon allowed Qingju Bike to eliminate multi‑code‑base maintenance, halve development time for new features, and achieve consistent performance across platforms. The case demonstrates how a well‑designed cross‑platform framework can drive business value by aligning technical decisions with product requirements.

frontendPerformancecross-platformComponentmini-programchameleonstore
Didi Tech
Written by

Didi Tech

Official Didi technology account

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.