跨平台是个非常热门、而且会是长久争论的话题。如今,技术人员所面临的平台选择非常多样,不同的平台会形成不同的技术势力,也称之为不同的技术栈或技术债。跨平台,如今讨论的主要是以下几个平台:
- PC端一脉:Windows,Linux,Mac OSX
- Mobile端一脉:Android,IOS,Google Fuchsia, Huawei Harmony等
- Console端一脉:Sony PSN, Microsoft XBOX;HTC Vive,Occlus Rift等 其他嵌入式如树莓派、Arudino等等。还有其他的如WindowCore,UbuntuTouch、Sailfish等等。
对于开发人员而言,不同的平台,实质上指的是:平台系统API环境,更大一点说,即平台系统的生态环境。
对于PC而言,Windows,采用WindowsNT为其系统核心,在其上先后存在MFC,ATL等等技术手段,最后推出了.NET全家桶作为技术生态圈;OSX有着BSC核心历史,在其上打造了Object-C这种反人类设计的编程语言的技术底层,并发展了COCOA等等各种技术,最近在大力发展Swift,打造Swift全家桶的同时,又想着兼容既有Object-C全家桶,相当纠结;Linux则百家争鸣、丰富多彩,以C语言为核心编程语言,没有固定于其上的束缚,对于开发人员而言,选择多样,非常自由。此三个平台,底层都以C语言为核心进行系统构建,也有配套的C语言开发环境,因此,对于跨PC平台而言,C或C++都是可以选择的,当然了,如果想要使用既有的生态圈,则需要去熟悉其全家桶使用的技术。
对于Mobile而言,Android,采用Linux内核,其上生态圈为Java;IOS,采用Apple一脉相承的BSD内核,以及Object-C生态圈,其Swift生态圈目前正在大力发展,但尚不完善;Fuchsia、Harmony目前尚在测试阶段,不予置评。
对于Console端而言,则都存在自己的开发套件。嵌入式、其他的操作系统,都是如此。
跨平台的核心意义在于:复用代码。编写一次,到处运行。不须担心在不同平台,有不同表现,需要进行适配等等。开发人员只需维护一套代码库,提高工作效率、降低维护成本、利于开发迭代。
C/C++
对于跨平台的开发而言,如果想与操作系统直接交互,C语言在目前为止是当之无愧的选择。C语言在操作系统层面由来以久,并且经过多年发展,其核心代码质量、性能都经过验证,想要从头以另外的语言来实现,工作量非常大,除非是非常激进、有财团支撑的公司或者能快速吸纳大量操作系统人才参与的开源项目才会作出此种选择。Rust的Redox是其中的一种尝试,目前仍是测试阶段。所以,对于操作系统层面,C语言仍将是首选语言,除非出现另一语言编写的操作系统能打破此局面。但,我觉得,10年内不会出现这种情况。原因如下:
- 世界上最多的操作系统人才,基本都或多或少为Linux内核贡献代码
- 操作系统作为最基本的软件,直接管理硬件资源,需要很多硬件厂商对其进行驱动支持。新操作系统,必须寻求他们的支持,否则只能另外聘任。这需要人力、财力。
- 作为操作系统,其性能、易用性都是首要考量标准,其次才是开发难度。
跨平台开发中,另一门语言是C++,C++是兼容C的,但在其上提供了许多适用于大型项目的特性,因此,对于操作系统应用层开发,C++既能直接的调用C语言(操作系统底层API),又能开发大型项目的特点,也常是跨平台开发的选择语言。
这里所说的C/C++是应用层与操作系统交互的编程语言。使用C/C++而言,其性能非常优秀,没有其他额外的层,直接调用了系统API。
跨平台语言
对于另一种常见方式,为跨平台的编程语言,如Python,Ruby,Rust,Go,C#,Java等等,这些语言要么是编译型,要么是解释型,都对操作系统API层进行了封装或抽象,提供了统一的操作系统接口,开发人员无需自行适配系统API,即可使用此统一接口。
C#,Java之流,提供了一层VM,将源码进行编译为VM识别的字节码或中间码,再由VM执行这些中间码。运行指令,由VM递送给操作系统。
Pyhton,Ruby,Elixir之流,提供了解释器(类似于VM),在运行时,动态解释代码,边解释,边运行。运行指令,由解释器递送给操作系统。
Rust,Go等,其跨平台的实质,与C/C++相同,都是使用跨平台的编译器实现。编译器对源码进行编译,形成二进制文件,直接由操作系统执行。在这种编译器中,如果要实现真正意义的跨平台,则需要实现交叉编译(即,在开发平台下,能编译出目标平台二进制文件)。这些语言通常会提供C语言FFI,直接能调用C语言库。
HTML + CSS + Javascript(前端)
这是另外一种快平台应用程序开发的方式,也是目前最为流行的。它从某种意义上说,也将Web当作了一个平台。其跨平台的基础支持,是基于:Web浏览器。无论在PC、Mobile,都存在Web浏览器,而Web浏览器,内嵌了Javascript解析器。只要某个平台有Web浏览器,即可使用此种组合。
Web浏览器,常见有这样几种:FireFox,Chrome,IE/Edge,Opera,Safari等,而Chrome和Safari有着相同的基因-webkit;FireFox有Gecko等等内核。这里,浏览器的内核主要包含两部分功能:语法解析与页面渲染。不同的浏览器,其根本是显示网页界面。网页内嵌Javascript,则可提供动态交互,其根本仍然是渲染。
对于不同的浏览器,其提供不同的Javascript解析器,提供的功能API也是不同的。早期,相同的前端代码,在不同的浏览器上,渲染出来的页面是有差异的,对于不同的浏览器,开发人员要做不同的适配工作。后来W3C统一标准,ECMA出台,化解这种差异,简化了开发人员的工作,这也使HCJ跨平台成为可能。
如今这种技术非常常见,微信小程序、支付宝小程序、React Native、Electron、Phone Gap等等,都是这种技术的实践者。
对于公司而言,前端技术人员好招、便宜、能快速看到效果,而且对于前端开发而言,毫无核心竞争而言,所有的动态效果,只要想要,在网上直接爬取即可获得大量优秀的动态效果,因此可以快速复用。
对于前端开发而言,只有一个核心追求:体验效果。通过前端技术开发的跨平台应用,性能是由渲染器和Javascript解析器——即内核——决定。
对于跨平台技术中,HTML+CSS+Javascript是铁三角,但也存在不同的实现方式:可转换的替代。可转换为Javascript的替代:如典型的CoffeeScript、Typescript、Dart等等,可编译成Javascript。
现在情况也有变化,WebAssembly的出现(Emscripten),直接在浏览器运行C/C++代码。这种技术,不仅仅可以提高运行效率,还能利用现有技术。
引擎+框架
对于跨平台开发而言,如今不仅仅只是功能开发,还是图形式开发,着重于视觉表现。因此,依照以上几种,衍生出另外一种跨平台开发形式:引擎+框架。
引擎,提供图形渲染和基本功能,提供访问系统API的能力,以此为基础,类似于前端的内核概念。框架,则是在引擎之上构建的应用框架内容,提供快速开发所需功能。
引擎+框架的形式,典型的是Flutter,Corona Labs,Cocos2d-x,Unity3d等。这种组合形式,是以提供自身渲染层为基础,所有的组件,都是通过自有渲染系统进行模拟渲染,达到一致效果。
总结
其实,综上所述,跨平台的技术,只有一种:引擎/内核+框架。引擎提供渲染、语言解释、系统API调用等等底层功能,框架提供UI组件、动画、效果等等。
我们回顾一下,跨平台应用的开发,核心聚焦在两点:渲染和开发环境。
对于渲染,有两种模式:系统自身渲染以及浏览器提供渲染,这称为既有渲染以及自行渲染。如果选择既有渲染模式,对于各个平台而言,提供了既有的技术和工具,可以方便开发,但有时候,这种开发套件的选择,也会束缚开发人员,导致跨平台成为一纸空文。对于前端技术而言,如我这种C++语言中毒者,很难对Javascript等产生好感,更不用提深入了解它们。对于跨平台语言而言,通常很难有直接的、官方的渲染层支持。
所以,对于跨平台开发,理想状态是:语言本身跨平台、渲染层跨平台、开发环境跨平台。
跨平台虽然看似深奥、难以实现,实则是比较简单、通俗的。
跨平台的最终目的是尽量复用代码的同时,性能、表现都一致。了解了这一基本前提,即可迅速理解当前所有的跨平台技术实现。
在这里,还是要多说一句:跨平台,不仅仅就只HTML+CSS+Javascript技术。