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 storeUse
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.jsonComponent 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