最近几年,随着前后端分离、单页面应用的崛起,网页正变得越来越应用化。移动互联网端的发展更是助长了这个趋势——对于交互、性能不敏感的场景,Web App在开发成本、跨平台兼容上有着明显优势。
但在这火爆的行情背后,很多时候从产品经理到设计甚至开发,对Web平台的特性并没有足够的了解与警觉,导致最终产品成了既不App也不Web的四不像,不仅拖累用户体验,开发团队也容易无所适用。
这篇文章希望围绕着Web的特性,探讨Web App与Native App的不同,帮助读者在项目中尽早地识别出可能出现问题的场景。
Web App is NOT App
Web App 也要按照基本法
Web App或者单页面应用(Single Page Application),名字里带个App,听起来颇有鸟枪换炮的味道,无论是工程师还是利益关系人(产品经理、客户),难免会有 和尚摸得我摸不得,App做得我做不得? 的错觉。更有甚者,把原生App的设计稿P上个浏览器地址栏就丢给团队,让照着做个Web App出来。如果这是你遇到的情况,那么恭喜,你已经在被坑的路上了
俗话说入乡随俗,既然运行在浏览器上,即使Web App能很大程度上提供 接近 App的体验,但有几点,是从根本上不同于App而又必须考虑的:
1. 应用入口与访问路径
App对用户的访问路径拥有近乎绝对的控制权:用户从哪些地方进入应用(图标、通知栏、分享链接)有限且可预测。而每一页提供的操作入口之和,都是用户当前可访问的子路径的 全集 。
而 Web对用户的访问路径控制权近乎为0 :任何页面的URL都是对用户可见的,用户可以添加书签,分享给亲友——任何页面都可能被直接访问, 必须 在设计和架构层面考虑。
鉴权和被访问并不矛盾:本文中被访问严格来讲是被用户请求,而鉴权或重定向则是对请求的处理
2. 刷新、后退、前进
这三个操作是所有Web浏览器工具栏的标准配置,而App多数情况下只需要考虑返回操作。
最麻烦是刷新:它会清空页面内存、重新发起请求、重新执行脚本。这意味着 Web端跨页面的内存数据是不可靠的 ,如果A页面依赖了B页面放在内存中的数据,下次刷新时得到的只会是 undefined 。
3. 上下文隔离
用户可能在应用或站点上进行一系列的、跨页面的操作,这些用户行为称为 上下文 ,而操作产生的数据(比如用户选择或表单输入),本文接下来称作 上下文数据 。
由于App对路径拥有绝对的控制权且不考虑刷新,某种程度上说App打开新的视图和在网页上打开模态窗的成本是一样的,下游页面可以假定上游页面生成的内存数据一定存在,而这些数据完全通过代码存取,对数据结构没有限制,因此 App端的上下文数据是复杂、可依赖的 。
反观Web,由于每个页面都可以被直接访问、刷新、甚至是复制链接到另一台设备上访问,存储在内存、LocalStorage中的数据都因此变得不可依赖,唯一能可靠传递的上下文信息 仅限于URL可以表征的数据 , 在没有服务器帮助的情况下,Web端的上下文数据是简单或不可依赖的 。
现代移动端浏览器提供了一种 应用模式 ,可以屏蔽浏览器工具栏,让页面更像原生App。然而现阶段真实应用的案例并不多见,并且至少有两个问题:
后退无法完全屏蔽:安卓平台的系统 返回 键等同于浏览器的 后退 。
移动端随时吃紧的内存可能导致当前不活动的页面被内存回收,下次打开时重新加载——相当于一次刷新。
为什么URL重要?
上面三点其实都围绕着核心——URL,某种程度上说, 整个Web世界都是被URL标识并驱动的,每个URL都应该定位到相应的资源
而现实的情况是:可能你在做一个面向消费者(以下称 2C )的项目,但需求方压根就没提URL和刷新的事;也可能你做的只是一个后台管理系统,不会有人在乎这东西,甚至会有一些和URL的定位特性相悖的需求。
这是最可怕的事,也是我写这篇文章的初衷:在真正遇到麻烦前,很少有人(甚至包括资深的前端工程师)会全面的思考这类问题,等掉到坑里的时候才发现积重难返。