你在给某连锁健身房做「会员扫码签到」系统。
需求很明确:
- 前台贴一张二维码,教练和会员都扫它;
- 教练用 PC 后台管理,要打开 Web 管理系统(React);
- 会员用手机扫码,要跳转 H5 轻应用(Vue);
结果第一版上线,会员扫完直接进了后台首页,一脸懵:"这表格是干啥的?"
你立刻意识到:同一个链接,必须智能分流。
解决方案:三层识别 + 渐进式加载
1. 表面用法:用 User-Agent 做第一道筛子
js
// router.js
const PC_UA = /Windows|Macintosh|Linux/;
const MOBILE_UA = /Android|iPhone|iPad|iPod/;
function getDeviceType() {
const ua = navigator.userAgent;
if (PC_UA.test(ua)) return 'pc';
if (MOBILE_UA.test(ua)) return 'mobile';
// 🔍 降级:看屏幕宽度
return window.innerWidth < 768 ? 'mobile' : 'pc';
}
js
// entry.js
async function main() {
const type = getDeviceType();
if (type === 'pc') {
await import('./web-app.js'); // 🔍 动态加载 PC 版
} else {
location.href = 'https://m.corp.com/app'; // 🔍 跳 H5
}
}
main();
关键点:
- PC 端直接加载 SPA,不跳转,体验无缝;
- 手机端跳转到独立 H5 域名,便于独立迭代和 SEO。
2. 底层机制:为什么不能只靠 UA?
识别方式 | 准确率 | 风险 | 适用场景 |
---|---|---|---|
User-Agent | 90% | 可伪造,部分平板 UA 模糊 | 快速分流 |
屏幕尺寸 | 85% | 折叠屏、横屏 iPad 易误判 | 降级兜底 |
触摸支持 | 95% | maxTouchPoints > 1 更准 |
辅助判断 |
最终用 组合判断 提升准确率:
js
function isMobile() {
const ua = navigator.userAgent;
if (/Android|iPhone/.test(ua)) return true;
if (/iPad|Macintosh/.test(ua) && 'ontouchend' in document) return true; // 🔍 iPadOS
return window.innerWidth <= 768 && navigator.maxTouchPoints > 1;
}
3. 设计哲学:把"分流"做成中间层服务
与其在每个项目里重复写判断逻辑,不如抽成一个 轻量级网关层:
js
// gateway.js (Node.js)
app.get('/entry', (req, res) => {
const { userAgent, 'x-forwarded-for': ip } = req.headers;
const isMobile = /Android|iPhone|Mobile/.test(userAgent);
if (isMobile) {
res.redirect('https://m.corp.com/app?from=' + ip); // 🔍 带来源信息
} else {
res.sendFile(path.join(__dirname, 'web/index.html')); // 🔍 直接吐 PC 页面
}
});
这样前端只维护一个入口页,逻辑全在服务端,便于灰度、埋点、拦截爬虫。
应用扩展:可复用的配置片段
1. 静态页分流模板(零后端依赖)
html
<!-- index.html -->
<script>
(function() {
const mobileRegex = /Android|iPhone|iPad|iPod|Mobile/;
if (mobileRegex.test(navigator.userAgent)) {
location.replace('https://m.corp.com/app');
}
// 否则继续加载 React/Vue 脚本
})();
</script>
2. 环境适配说明
场景 | 注意点 |
---|---|
微信内置浏览器 | UA 含 MicroMessenger ,但仍是 mobile,正常跳 H5 |
iPadOS | 默认 UA 像 Mac,需检测 ontouchend 或 maxTouchPoints |
PWA 安装后 | window.matchMedia('(display-mode: standalone)') 可识别,但分流不依赖它 |
举一反三:3 个变体场景
- App 内嵌 H5 智能跳转
在 UA 里加自定义字段MyApp/1.0
,识别到后跳myapp://page/signin
唤起原生页。 - PC 平板混合设备(Surface)
先按 PC 加载,但监听页面touchstart
事件,3 秒内有触摸则提示:"检测到触屏,是否切换平板模式?" - AB 测试分流
在 gateway 层加逻辑:Math.random() < 0.1
的 mobile 用户强制看 PC 版,收集体验反馈。
小结
别让设备类型决定代码,而要让代码聪明地认识设备。
用 UA 做快筛,尺寸和触摸做兜底,服务端做管控,一个链接也能走出两条路。