写 Mpx 跨端项目,最崩溃的不是业务难,是 同一个 Hook,五个端五种写法

登录?小程序 wx.login,iOS 走原生 SDK,Web 又是 H5 授权页。
你要是在一个 login.ts 里堆 @mpx-if,删到 300 行的时候,review 的同事会沉默,你也会沉默。

我后来换了个套路:文件级分包 + base.ts 定契约

🤔 两种常见坑法

坑法一:一个文件 @mpx-if 到吐

/* @mpx-if (__mpx_mode__ === 'ios') */
import sdk from '@vendor/login-ios'
/* @mpx-else */
import sdk from '@vendor/login-wx'
/* @mpx-endif */

三个平台还能忍,七个平台就是灾难片。

坑法二:运行时到处是 if

if (isIOS) { ... } else if (isWx) { ... } else if (isWeb) { ... }

测试矩阵?你自己算算要测多少组合 😰

💡 正确打开方式:按端拆文件,对外同一个名字

目录长这样:

hooks/login/
  base.ts           ← 只有类型,零平台 API
  index.ts          ← 默认端(一般是小程序)
  index.ios.ts      ← iOS / DRN
  index.android.ts
  index.web.ts
  index.wx.ts       ← 可选,微信特别逻辑再拆
hooks/index.ts      ← 统一 export,页面只引这里

Mpx 构建时会按 target 自动找 index.ios.ts,你不用在业务里写 import './login/index.ios'——写了反而跨端编译会乱。

📝 base.ts:先把「约定」规定好

// hooks/login/base.ts
export interface LoginOptions {
  page?: 'auth' | 'phone'
  protocols?: string[]
}

export interface LoginResult {
  token: string
  uid: number | string
  phone: string
  openid: string
  status: null | 'success' | 'fail' | 'logout'
}

各端返回 同一形状,上层才不用写 if (isIOS)
base.ts不要 import 任何平台 SDK,否则所有端都会被打进包里,体积直接起飞。

🍎 index.ios.ts:填 iOS 的实现

import type { LoginOptions, LoginResult } from './base'
import mpxLogin from '@vendor/mpx-login'

export const login = async (options?: LoginOptions): Promise<LoginResult> => {
  const res = await mpxLogin.login(options)
  if (!res) return Promise.reject(res)
  return {
    token: res.ticket,
    phone: res.phone.value,
    uid: res.uid,
    openid: res.openid,
    status: 'success',
  }
}

export const isLogin = async () => {
  const res = await mpxLogin.isLogin({ needTempTicket: true })
  // ... 映射成 LoginResult
}

小程序端 index.ts、Web 端 index.web.ts 函数名一模一样,只是里面调的东西不同。

🎯 页面层:干净得像没跨端过

import { login, isLogin } from '@/hooks/login'

async function handleLogin() {
  const info = await login({ page: 'auth' })
  console.log('谁管你是哪端,反正有 token', info.token)
}

🤷 @mpx-if 还要不要?

要,但别滥用:

| 差 1~3 行样式(safe-area、padding) | @mpx-if 够了 |
| 差一整段 API 调用 | index.{platform}.ts |
| 同一文件里 3 个以上 @mpx-if 块 | 该拆了,别硬撑 |

我的口诀:逻辑差 ≥10 行 → 拆文件;样式差 → 条件编译。

🕳️ 下面这些坑我踩过

  1. base.ts 偷偷 import 了平台库 → 包体积暴涨,查半天
  2. iOS 返回字段和小程序不一样 → 上层又开始写 if,白拆了
  3. 某一端忘了建 index.xxx.ts → 静默 fallback 到 index.ts,预发没事但生产暴雷
  4. 枚举值是 0 → 别写 if (!actionType),用 === undefined

🎬 最后说两句

跨端 Hook 的核心就一句话:差异关进文件里,对外只暴露一个名字。

Logo

一站式 AI 云服务平台

更多推荐