<audio id="audio" title="24 | 跨平台与 Web 开发的建议" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/76/18/76c367e9cfcfc4256a656a08c244e718.mp3"></audio>

你好，我是七牛云许式伟。

上一讲我们聊了浏览器，以及移动浏览器之争：小程序与 PWA。

当我们思考浏览器从技术上带来了什么的时候，我们可以把它分为两点。

- 跨平台桌面程序开发；
- Web 开发（B/S 架构的新型应用）。

今天我们分别就跨平台桌面程序和 Web 开发展开来聊一聊。

## 跨平台桌面程序开发

跨平台的桌面程序开发是一个超级难题。无数人前仆后继，各种方案层出不穷，但至今为止，仍然没有称得上真正深入人心的解决方案。

原因很简单，因为桌面程序本身的范畴在变。有两个关键的因素会导致桌面开发产生巨大的差异性。

一个因素自然是操作系统。不同的操作系统抽象的界面程序框架并不一致。这些不一致必然导致开发工作量的增加。

放弃某个操作系统，就意味着放弃某个流量入口，也就意味着放弃这些用户。所以虽然很麻烦，我们还是不得不支持着每一个主流的操作系统。

另一个因素是屏幕尺寸。就算相同的操作系统，在不同尺寸的屏幕上，交互的范式也会存在很大的差异性，这也会导致不低的跨平台工作量。

首先我们看下操作系统。

- PC 本地：Windows，macOS，Linux 等等；
- PC Web：Chrome，Safari，FireFox 等等；
- Mobile 本地：Android，iOS 等等；
- Mobile Web：小程序，PWA 等等。

我们再看下屏幕尺寸。

- 大屏：PC、笔记本，Pad 等等；
- 中屏：手机；
- 小屏：手表。

如此繁复多样的终端类型，无怪跨平台如此之难。我们来总结一下当前都有哪些跨平台的解决方案。

<img src="https://static001.geekbang.org/resource/image/da/c7/daf115d3a745c302026b914ee760ccc7.jpg" alt="">

这个列表只是沧海一粟。之所以没有列那么多，也是因为大部分的跨平台框架都已经不怎么活跃，已经无疾而终了。

目前来说，还很难说哪个方案会胜出。

关于跨平台开发，我觉得有一句话特别深刻：“每一次统一的努力，都最终变成新的分裂”。当然，这样的事情在很多领域都会发生，只是跨平台开发更加如此。

但是无论如何，跨平台的梦还会继续。

## Web 开发

聊完了跨平台，我们来聊聊浏览器带来的另一面：Web 开发。

Web 的 B/S 架构意味着编写软件有了更高的复杂性。这主要表现在以下几个方面。

**其一，多用户。**有了 Server 端，意味着用户的数据不再是保存在 Client（Browser）端，而是存储在 Server 端。

**其二，更高的数据可靠性要求。**数据在 Client 端，客户自己对数据的可靠性负责。硬盘坏了，数据丢了，用户会后悔没有对数据进行备份。

但是一旦数据在 Server 端，数据可靠性的责任方就到了软件厂商这边。如果厂商不小心把数据搞丢了，用户就会跳起来。

**其三，更多可能的分工安排。**详细来说，Web 应用从流派来说，分为两大类：胖前端与胖后端。

所谓胖前端，是指把尽可能多的业务逻辑放在前端。极端情况下，整个网站就是一个单页的应用。胖前端无论开发体验还是用户体验，都更接近于本地应用（Native App）。

所谓胖后端，是指主要逻辑都在后端，包括界面交互的事件响应，也通过网络调用交给了后端来实现。

我们先看客户端（Client），也就是浏览器端（Browser）。上一讲我们提到，浏览器的界面框架并没有窗口系统，它通过 HTML+CSS 来描述界面。

HTML+CSS 与其理解为 View 层，不如理解为 ViewModel 层，因为 HTML DOM 从数据角度完整描述了界面的样子。而 View 层已经被浏览器自己实现了。

这极大简化了界面开发的复杂性，因为界面的局部更新是一个复杂的话题，今天浏览器通过引入 HTML+CSS 这样的 ViewModel 层把它解决了。

这个时候我们重新看 MVC 框架在浏览器下的样子，你会发现它变成了 MVMP 模式，全称为 “Model-ViewModel-Presenter”。

<img src="https://static001.geekbang.org/resource/image/94/7f/94475e49c61f8dfbadb2448c7bc72b7f.png" alt="">

**首先，我们看事件响应过程。**浏览器的 View 收到了用户的交互事件，它把这些事件委托（delegate）给了 ViewModel 层，并且通过 HTML DOM 暴露出来。通过修改 HTML 元素的事件响应属性，一般名字叫 onXXX（比如 onclick），可以获得事件的响应机会。

**然后我们看 Model 层的数据变化（DataChanged）事件。**在标准的 MVC 模式中，Model 层的数据变化是通知到 View 层，但是在浏览器下 View 是由浏览器实现的，要想让它接受 DataChanged 事件并且去处理是不太可能了。

所以解决思路自然是让 Controlller 层来做，这样就变成了 MVP 模式。 但是我们又不是标准的 MVP，因为 Presenter 层更新界面（Update View）并不是操作 View，而是 ViewModel。

**综上，浏览器下的 MVC，最终实际上是 MVMP（Model-ViewModel-Presenter）。**

聊完了浏览器端，我们在来看下服务端（Server）。虽然这一章我们的重点不是聊服务端，但是为了有个完整的认识，我们还是要概要地梳理一下 Server 端的架构。

<img src="https://static001.geekbang.org/resource/image/7d/c2/7d4754709350d95b8afe0aa35e6e6dc2.jpg" alt="">

前面我们在 “[22 | 桌面程序的架构建议](https://time.geekbang.org/column/article/105356)” 中，曾提到桌面软件除了要支持用户交互外，另一个很重要的需求是提供应用程序的二次开发接口（API）。

到了 Web 开发，我们同样需要二次开发接口，只不过这个二次开发接口不再是在 Client 端完成的，而是在 Server 端完成。Server 端支持直接的 API 调用，以支持自动化（Automation）方面的需求。

所以，对 Server 端来说，最底层的是一个多租户的 Model 层（Multi-User Model），它实现了自动化（Automation）所需的 API。

在 Multi-User Model 层之上，有一个 Web 层。Web 层和 Model 层的假设不同，Web 层是基于会话的（Session-based），因为它负责用户的接入，每个用户登录后，会形成一个个会话（Session）。

如果我们对Web 层细究的话，又分为 Model 层和 ViewModel 层。为了区分，Web 这边的 Model 层我们叫它 Session-based Model。相应地，ViewModel 层我们叫它 Session-based ViewModel。

在服务端，Session-based Model 和 Session-based ViewModel 并不发生直接关联，它们通过自己网络遥控浏览器这一侧的 Model 和 ViewModel，从而响应用户的交互。

Session-based Model 是什么样的呢？它其实是 Multi-User Model 层的转译。把多租户的 API 转译成单租户的场景。所以这一层并不需要太多的代码，甚至理论上自动实现也是有可能的。

Session-based ViewModel 是一些 HTML+JavaScript+CSS 文件。它是真正的 Web 业务入口。它通过互联网把自己的数据返回给浏览器，浏览器基于 ViewModel 渲染出 View，这样整个系统就运转起来了。

## 结语

今天我们聊了 Web 带来的两个重要改变。一个是跨平台，一个是 Web 开发，即 B/S 架构下的新型应用到底应该怎么实现。

从跨平台来说，这个话题是桌面程序员（也叫“大前端”）永远的痛。计划赶不上变化，用来形容大前端程序员面临的窘境是一点都不过分的。一个玩意还没搞熟悉了，另一个东西又出来了，变化太快，要跟上实属不易。

从 Web 开发来说，MVC 变成了 MVMP（Model-ViewModel-Presenter）。我们和单机的桌面软件一样的建议，认真对待 Model 层，认真思考它的使用接口是什么样的，把 Model 层做厚。

如果你对今天的内容有什么思考与解读，欢迎给我留言，我们一起讨论。下一讲我们将结合一个实际的案例，来讲解一下桌面开发（含单机软件和 Web）到底是什么样的。

如果你觉得有所收获，也欢迎把文章分享给你的朋友。感谢你的收听，我们下期再见。
