Skip to content
Created: December 26, 2019

1. Project goals (preliminarily set design principles) ​

The goals of this set of templates are:

  • ✅ Thin pages and centralized logic
  • ✅ Testable and scalable
  • ✅ Avoid setData performance pit
  • ✅ Comply with WeChat review & specifications
  • ✅ Does not rely on heavy frameworks (native + light packaging)

Suitable for: native applet / Taro / uni-app, all thinking can be applied

2. Recommended directory structure (core) ​

miniprogram/
├─ app.js
├─ app.json
├─ app.wxss

├─ pages/                    # 页面(只放 Page 壳)
│  ├─ home/
│  │  ├─ index.js
│  │  ├─ index.wxml
│  │  ├─ index.wxss
│  │  └─ index.logic.js      # 页面业务逻辑
│  └─ detail/
│
├─ components/               # 通用组件
│  ├─ Base/
│  │  ├─ Button/
│  │  ├─ Modal/
│  └─ Business/              # 业务组件
│     └─ ProductCard/
│
├─ services/                 # 所有接口层
│  ├─ request.js             # 请求封装
│  ├─ auth.js                # 登录 / token
│  ├─ user.api.js
│  └─ order.api.js
│
├─ store/                    # 全局状态
│  ├─ index.js
│  └─ user.store.js
│
├─ utils/                    # 工具函数
│  ├─ logger.js
│  ├─ debounce.js
│  ├─ validate.js
│  └─ env.js
│
├─ config/                   # 配置
│  ├─ index.js
│  ├─ api.config.js
│  └─ permission.config.js
│
├─ constants/                # 常量
│  ├─ error-code.js
│  └─ storage-key.js
│
├─ styles/                   # 全局样式
│  ├─ variables.wxss
│  └─ mixin.wxss
│
└─ subpackages/              # 分包
   └─ profile/

3. Page “slimming” mode (very important) ​

❌ Wrong approach ​

js
Page({
  data: {},
  onLoad() {
    wx.request(...)
  },
  onTap() {
    // 一堆业务逻辑
  }
})

✅ Correct approach: Page + Logic separation ​

pages/home/index.js ​
js
import logic from './index.logic'

Page({
  ...logic
})
pages/home/index.logic.js ​
js
import { getHomeData } from '../../services/home.api'

export default {
  data: {
    list: []
  },

  async onLoad() {
    const data = await getHomeData()
    this.setData({ list: data })
  },

  onItemTap(e) {
    const id = e.currentTarget.dataset.id
    wx.navigateTo({ url: `/pages/detail/index?id=${id}` })
  }
}

👉 Benefits:

  • The page is just a "shell"
  • Logic is testable
  • Can be migrated to Taro / React later

4. Request layer design (the most critical) ​

1️⃣ request package ​

services/request.js ​

js
import { getToken } from './auth'

const BASE_URL = 'https://api.xxx.com'

export function request(options) {
  return new Promise((resolve, reject) => {
    wx.request({
      url: BASE_URL + options.url,
      method: options.method || 'GET',
      data: options.data || {},
      header: {
        Authorization: getToken()
      },
      success(res) {
        if (res.statusCode === 200) {
          resolve(res.data)
        } else {
          reject(res)
        }
      },
      fail(err) {
        reject(err)
      }
    })
  })
}

2️⃣ API sub-module ​

services/user.api.js ​

js
import { request } from './request'

export function getUserInfo() {
  return request({
    url: '/user/info'
  })
}

👉 It is forbidden to write wx.request in Page

5. Global state management (lightweight) ​

store/index.js ​

js
const store = {
  user: null,
  setUser(user) {
    this.user = user
  }
}

export default store

Use ​

js
import store from '../../store'

store.setUser(res)

👉 Mini programs are not suitable for Redux-heavy solutions 👉 "If you can't use the global system, don't use it"

6. setData performance specifications (must be written into team specifications) ​

❌ Prohibited ​

js
this.setData({ bigList })
this.setData({ count })

✅ Recommended ​

js
this.setData({
  'bigList[3].title': 'xxx'
})

Agreement ​

  • setData ≤ 1 times/event
  • Large object split fields
  • List loading in pages

7. Component design specifications ​

Component structure ​

ProductCard/
├─ index.js
├─ index.wxml
├─ index.wxss
└─ index.json

Component communication ​

  • parent → child: properties
  • child → parent: triggerEvent
  • ❌ Do not directly operate the parent data

8. Configuration & Environment Isolation ​

config/env.js ​

js
export const ENV = 'prod'

config/api.config.js ​

js
export const API_HOST = {
  dev: 'https://dev.api.com',
  prod: 'https://api.com'
}

9. Subcontracting design (must be done before going online) ​

json
{
  "subpackages": [
    {
      "root": "subpackages/profile",
      "pages": ["index"]
    }
  ]
}

👉 Main package ≤ 2MB 👉 Full advance subcontracting of non-first-screen pages

10. Checklist that you can reuse directly ​

  • ✅ Page + logic separation
  • ✅ API layer concentration
  • ✅ Business code is prohibited from entering Page
  • ✅ Subcontracting
  • ✅ setData specification
  • ✅ Delay in permission application