简介
本文件面向 DouPHP 的跨平台兼容性处理,聚焦小程序与 Web 端的 JavaScript 差异、API 兼容、事件系统差异、平台特性适配与降级策略。文档基于仓库中小程序端(miniprogram)与主题前端(theme)的实际代码,给出可落地的实现路径、流程图与时序图,并覆盖主流浏览器(IE、Chrome、Safari、Edge)的特殊处理要点,同时提供测试与调试建议。
项目结构
- 小程序端位于 miniprogram/default,包含应用入口、HTTP 层、环境探测、类型定义等。
- Web 端主题位于 _'theme/*,包含多套主题的 JS/CSS,涵盖 UA 检测、CSS3 前缀兼容、滚动与动画兼容等。
- API 层位于 api/controller,提供微信登录等后端能力,配合小程序端完成鉴权与业务闭环。
graph TB
subgraph "小程序端"
A["app.ts<br/>应用初始化/更新/错误钩子"]
B["http.ts<br/>统一请求封装/信封解析/缓存去重"]
C["env.ts<br/>运行环境与调试开关"]
D["wx index.d.ts<br/>小程序API类型声明"]
end
subgraph "Web端主题"
E["css3-mediaqueries.js<br/>UA检测/特性检测"]
F["slide.js<br/>CSS3前缀/过渡事件兼容"]
G["script.js<br/>浏览器/设备识别"]
H["jquery.nicescroll.js<br/>滚动/指针事件兼容"]
end
subgraph "后端API"
I["WeixinController.php<br/>小程序登录/会话"]
J["WxPay.Data.php<br/>支付参数封装"]
end
A --> B
A --> C
B --> D
E --> F
E --> G
E --> H
B --> I
I --> J
核心组件
- 小程序应用入口:负责全局初始化、自动更新、调试模式、推广参数解析、导航栏高度计算等。
- 统一 HTTP 层:封装 wx.request,统一信封解析、拦截器、内存缓存、请求去重、调试增强。
- 环境探测:判断当前是否为非正式版(develop/trial),镜像服务端 debug 开关。
- Web 端兼容层:UA 检测、CSS3 前缀与事件兼容、滚动与指针事件兼容。
- 后端接口:小程序登录流程、支付参数封装。
架构总览
小程序与 Web 端通过统一的 API 信封进行通信;小程序侧通过 http.ts 统一发起请求,后端返回标准信封(code/message/data/errors/request_id)。Web 端通过 UA/特性检测选择兼容实现,确保在不同浏览器下行为一致。
sequenceDiagram
participant MP as "小程序 app.ts"
participant HTTP as "http.ts"
participant WX as "wx.request"
participant API as "WeixinController.php"
participant PAY as "WxPay.Data.php"
MP->>HTTP : 调用 get/post/put/del
HTTP->>WX : 发送请求(带Authorization头)
WX-->>HTTP : 响应体(可能为字符串或JSON)
HTTP->>HTTP : 解析信封(code===OK为成功)
alt 成功
HTTP-->>MP : data<T>
else 失败(HTTP/业务码)
HTTP-->>MP : ApiError(含request_id)
end
Note over MP,HTTP : 调试模式下附加request_id便于定位
详细组件分析
小程序应用入口(app.ts)
- 职责:注册全局错误钩子、自动更新、推广参数解析、导航栏高度计算、调试模式开启。
- 关键流程:
- onLaunch:初始化全局 store、读取窗口/设备信息、计算导航栏高度、启动自动更新、调试期开启 vConsole。
- onError/onUnhandledRejection/onPageNotFound:统一日志输出与调试弹窗。
- parsePromotionFromLaunchOptions:兼容 scene/query 多种打开来源,解析 user_sn 并写入本地存储。
- autoUpdate:使用 canIUse('getUpdateManager') 做能力检测后执行更新流程。
flowchart TD
Start(["App.onLaunch"]) --> InitStores["引导全局store"]
InitStores --> GetInfo["获取窗口/设备信息"]
GetInfo --> CalcNav["计算导航栏高度"]
CalcNav --> AutoUpdate{"canIUse('getUpdateManager')?"}
AutoUpdate --> |是| UpdateFlow["检查/提示/应用更新"]
AutoUpdate --> |否| SkipUpdate["跳过更新"]
UpdateFlow --> End(["结束"])
SkipUpdate --> End
统一 HTTP 层(http.ts)
- 职责:统一信封解析、默认头注入、拦截器机制、GET 去重、内存缓存+TTL、调试增强。
- 关键点:
- 信封解析:严格读取 code/message/data/errors/request_id,code==='OK'视为成功。
- 请求去重:相同 GET 在飞行中复用 Promise,避免重复请求。
- 缓存:支持 cache/ttl/revalidate,命中直接返回。
- 方法伪装:PUT/DELETE 通过 POST + _method 字段承载,适配 PHP $_POST 解析限制。
- 调试:isDebugEnv() 控制是否弹出服务端异常堆栈、追加 request_id 到消息。
classDiagram
class RequestConfig {
+string url
+Record~string, any~ data
+string method
+Record~string, string~ header
+string responseType
}
class RequestOpts {
+boolean cache
+number ttl
+boolean revalidate
+boolean dedupe
}
class ApiError {
+string code
+number statusCode
+Record~string, string~ errors
+Record~string, any~ data
+string request_id
}
class HttpService {
+request(config, opts) Promise
+get(url, data, opts) Promise
+post(url, data, opts) Promise
+put(url, data, opts) Promise
+del(url, data, opts) Promise
+clearCache(prefix) void
+getLastRequestId() string
+onRequest(fn) void
+onSuccess(fn) void
+onError(fn) void
}
HttpService --> RequestConfig : "使用"
HttpService --> RequestOpts : "使用"
HttpService --> ApiError : "抛出"
环境探测(env.ts)
- 功能:isDebugEnv() 判断当前是否为非正式版(develop/trial),回退读取 __wxConfig;isServerDebug() 镜像服务端 debug_enable。
- 用途:控制调试 UI(vConsole、错误弹窗)、服务端调试开关。
Web 端兼容层(主题 JS)
- UA 检测与特性检测:
- css3-mediaqueries.js:检测浏览器内核、版本、移动端标识,提供 domReady 兼容。
- script.js:识别 IE/Edge/移动端,用于条件分支。
- CSS3 前缀与事件兼容:
- slide.js:检测 transform/transitionend 前缀,映射不同浏览器的事件名。
- jquery.nicescroll.js:检测 transition 前缀与事件名,处理 IE/Chrome 特殊行为。
- 滚动与指针事件:
- 针对 IE7/8 强制 overflow-y 滚动,避免布局问题。
- 兼容 touch/mouse/pointer 事件,保证交互一致性。
flowchart TD
WStart["页面加载"] --> DetectUA["UA检测<br/>css3-mediaqueries.js/script.js"]
DetectUA --> FeatureTest{"特性检测"}
FeatureTest --> |支持现代API| UseModern["使用原生API"]
FeatureTest --> |不支持| Fallback["降级方案<br/>前缀/事件映射"]
Fallback --> ApplyPrefix["添加vendor前缀"]
ApplyPrefix --> MapEvents["映射transitionend/pointer事件"]
UseModern --> Ready["渲染/交互正常"]
MapEvents --> Ready
小程序特有 API 封装与 Web 对应实现
- 小程序侧:
- 使用 wx.request 发起网络请求,统一信封解析与错误处理。
- 使用 wx.getUpdateManager 进行版本更新,先 canIUse 检测。
- 使用 wx.getAccountInfoSync/__wxConfig 判断运行环境。
- Web 侧对应:
- 使用 fetch/XMLHttpRequest 发起请求,需自行实现信封解析与错误处理。
- 使用 location.reload()/service worker 等机制实现更新提示。
- 使用 navigator.userAgent 与特性检测实现环境识别与降级。
后端登录与支付集成
- 小程序登录:WeixinController.php 接收 code,调用微信接口换取 openid/session_key,完成用户绑定与登录态管理。
- 支付参数:WxPay.Data.php 提供统一下单等参数封装,确保字段齐全与校验。
依赖关系分析
- 小程序端依赖:
- app.ts 依赖 http.ts、env.ts、类型定义 index.d.ts。
- http.ts 依赖 env.ts 与 wx API 类型。
- Web 端依赖:
- 各主题 JS 相互独立,但共享 UA/特性检测逻辑。
- 后端依赖:
- WeixinController.php 依赖配置与数据库。
- WxPay.Data.php 作为 SDK 被上层调用。
graph LR
App["app.ts"] --> Http["http.ts"]
App --> Env["env.ts"]
Http --> WxTypes["wx index.d.ts"]
ThemeJS["主题JS"] --> UADetect["UA/特性检测"]
Http --> API["WeixinController.php"]
API --> PaySDK["WxPay.Data.php"]
性能考量
- 小程序端:
- GET 请求去重与内存缓存减少重复网络开销。
- TTL 控制缓存有效期,避免脏数据。
- 调试模式仅在非正式版启用,降低生产开销。
- Web 端:
- 特性检测优先使用原生 API,避免不必要的 polyfill。
- 对旧浏览器采用最小化降级,减少脚本体积。
故障排查指南
- 小程序端:
- 统一错误对象 ApiError 携带 code/statusCode/errors/request_id,便于定位。
- 调试模式下弹出服务端异常堆栈,复制 JSON 便于上报。
- 未捕获异常与未处理 Promise 拒绝统一记录。
- Web 端:
- 通过 UA 检测与特性检测定位兼容性问题。
- 对 IE7/8 等特殊浏览器进行滚动与样式降级。
结论
DouPHP 在小程序与 Web 端采用了分层兼容策略:小程序侧通过统一 HTTP 层与环境探测屏蔽差异,Web 侧通过 UA/特性检测与前缀/事件映射保障一致性。后端提供标准化的登录与支付能力,配合前后端协作实现跨平台体验。建议在新增功能时遵循“能力检测优先、降级兜底”的原则,并在调试阶段充分利用 request_id 与调试弹窗快速定位问题。
附录
- 跨平台开发最佳实践:
- 条件编译:基于 isDebugEnv() 与 canIUse 进行运行时分支。
- 特性检测:优先检测 API 可用性,再决定实现路径。
- 降级方案:为旧浏览器提供最小可用体验。
- 测试策略:
- 小程序:使用 develop/trial/release 三套环境验证功能与更新流程。
- Web:覆盖 IE、Chrome、Safari、Edge,重点验证滚动、动画、触摸事件。
- 调试技巧:
- 小程序:开启 vConsole,利用 ApiError 的 request_id 与服务端日志对照。
- Web:使用浏览器开发者工具,结合 UA 检测输出定位兼容点。