面对4大瓶颈,前端开发的未来在哪里?
你会为了精确还原设计稿熬夜加班,从而练就一双像素眼;
你会因为某些技术问题和同事理论,最终到达到与产品谈笑风声的境界;
你会为了解决几个字节的性能问题研究优化方案,以至看懂了每一个 HTTP 请求头;
.........
但是随着时间的推移,前端技术的更新迭代,以及互联网的发展。你会发现这些曾经的问题似乎已经不再是问题,或者说在能预见的未来可能不再是问题。
页面加载性能可能不再是问题,技术上有了HTTP2,基建上有了5G,硬盘也越来越快。兼容性问题慢慢淡出大家的视角,Chrome一家独大,微软也不得不向它靠拢。很多前端开发已经具备了后端(或者说多端)的技术能力,技术储备也可能不是问题,当然前提是你能招到人。
到底什么是前端开发?前端与后端的界限在哪里?在三年前我对它的定义是:前端为界面、交互展示负责;后端为数据、业务逻辑负责。不过现在看来似乎已经过时了,我越来越觉得不应该有这样一个清晰的界限把前后端分割开来,尤其是技术层面(除了职能层面的界限有利于协作以外)。这就好比说:如果你不能打破规则,那就必将被规则束缚。
我一直认为程序员应该对新的技术、工具、理念有比平常人更快的适应能力。举个简单的例子,我以前写代码通常使用tab缩进,后来大家都建议使用空格,刚开始尝试换成空格肯定是拒绝的,因为让人改变习惯是一件很难的事情。但是当你真正为了改变做出实践的时候,往往就会发现一条新大路。同样还有加不加分号的问题。
现在回过头来再看,前端在整个系统层面担任的角色至少应该是整个视图View 层面的。视图层面的技术更接近软件系统的上层,更感性。感性的东西就比如说一个颜色,我觉得好看,他觉得不好看,完全属于个人情感诉求。所以前端更注重与UI、交互以及整个产品层面需要解决的问题。优秀的前端必然要具备敏锐的产品洞察能力。当然这还只是前端最基础的职责所在。同时前端做为最接近产品的技术角色,技术才是前端真正的硬实力。
大约在去年一年的时间,我的岗位从前端转向了后端Java程序员的角色。虽然只做了一年的Java程序员,但是对我自身的技术提升而言是最多的一年。大家可能普遍的认为后端转前端比较容易,前端转后端会有门槛,实际上根据我自己的体验来讲并非如此。
Java这门语言是商业化、成熟度特别高的语言。无论是语言本身,还是周边框架、工具都有一套非常成熟且层次分明的系统化抽象。如果你有两三年的编程经验,突然让你上转写Java是非常容易的一件事情,尤其是写Java web。Spring框架已经为程序员屏蔽了很多复杂问题,而且已经事实上成为了各大互联网公司的主流框架选型。
我特意按我自己的学习线路绘制了一张Java版的程序员学习线路,仅供参考:
我们可以清楚的看出来Java构建的整个体系最大的特点:它是渐进式的,一步一步地给开发者建立正向的引导。
当我处在在应用层阶段的时候,我需要关心的只是一些概念、方法,具备基础了以后就可以借助Spring框架入门,入门后就可以研究源码,你会发现Spring 的本质核心类DispatchServlet,从此Servlet就出现在了你的视野。我以前上学时理解不了java中Servlet 的概念,后来参加了工作又学些了Python,再次看到Java中的Servlet 的时候瞬间就明白了它就是Python中的uwsgi,就是一种接口,将编程语言和服务器网关链接起来的一种规范。
然后你就可以顺利进入下一环节,服务器/通信。这里你会发现整个网络编程的核心Socket,同样以前上学的时候没理解Socket的概念,继续学习后你就会明白Socket其实就是操作系统提供给编程语言的一种能力,有了它就可以建立服务器与客户端之间的通信。在这一环节中你会学习到网络层TCP/IP协议,明白了TCP/UDP的区别,while (true) { socket.listen() }
建立Socket 监听会有性能问题,此时你便进入下一个抽象层次,操作系统和计算机原理。
为了解决while true监听连接的性能问题,你会去学习多线程技术,了解并发的概念。你可能总会听到别人讨论并发和并行的区别。继续学习后,慢慢的你就会明白:并发多用来解决网络IO(硬盘)的效率问题,而并行则是为了更好的利用多/核处理器(CPU)的问题。这时你会发现这个阶段涉及到了很多的计算机硬件知识。内存分配、CPU计算、IO复用等等。
像Spring这种框架才能真正意义上被称做框架,因为它不仅仅解决了软件开发的问题,更重要的是AOP/IOC这类概念可以完全改变编程的一些理念。使用 Spring开发web应用,联合Java 构建出来的生态,整个开发流程就像呼吸一样自然。
Java构建出来的软件开发体系就像是把程序员放进了一个一个的层次分明的小柜子里面,进去了以后你根本不需要关注外界是怎么样的,做好自己那部分工作就可以了。如果你对外界有兴趣可以一点点的顺藤摸瓜,跳出你原来的小柜子。即保证精力专注的同时又建立起一套有秩序的提升曲线。这一点是别的语言体系没有的。
实际上我在转Java之前对Java有着不小的误解,甚至转Java本身也不是我自己的想法。但当你真正转型成Java程序员后。看懂了数以百万行记的代码仓库、维护过每秒好几十万的QPS项目、见识过百行的SQL的时候,你才会对Java和软件开发产生一种敬畏之心,才会对技术才有了更深层次的理解。
这时候再回过头来看前端,看JavaScript,才会发现它们之间的区别与特点。很多之前争论的东西也就有了结论。
我相信从事前端工作稍微长一点(5年以上)的人近两年都会有一种感觉:前端似乎没什么东西可以玩出花样了。这是因为很多东西都已经成为了前端事实上的主流,以前前端没有的基建慢慢的被完善。语言、框架、可视化、跨端、游戏、工具/自动化/工程化 这些领域都在发展。
语言方面TypeScript必然是主流,无论你愿意与否,你都将不得不使用它来写前端。框架方面React已经是事实上的主流了,没必要再做选择题。打包工具 Webpack也是一家独大,虽然被很多人诟病,但是社区生态起来了,想改变就很难。跨端应用Electron也不用想了,VSCode能做好你做不好那就不是选型的问题了。2D游戏/绘图方面PixiJS 6已经在设计中了,3D我个人认为就先别玩了。
这些看似成熟的体系实际上还是有很多可以挖掘的东西。如果你不深入研究,或许会认为过两年这些技术就稳定了前端就可以做到大一统的状态。这个想法可能就过于天真了,我举例解释下它们各自的瓶颈:
前/客户端框架的瓶颈
React(并不特指 React)虽然现在看起来是主流,但是它本身有很多问题是没解决的,甚至可以说是无解的。React的本质只是一个UI Library,并不是框架Framework。框架要解决的问题是系统层面的不是某个抽象层面的。用 React写过几个项目以后你就会认识到用React去写大型项目是非常麻烦的事情,React本身并不解决SPA应用中数据流的问题,甚至没解决状态管理的问题(或者说状态管理本来就是个伪命题?)。一个很简单的父子组件之间状态共享的问题一直没有成熟的解决方案,hooks这种方案更像是拆了东墙补西墙。
而且现在React社区弥漫着一种崇尚函数式编程的邪气,hooks更像是一块遮羞布。多数人用hooks的原因仅仅是不想使用Class,因为Class很臃肿,function更简单。当然这个逻辑是没问题的。函数确实简单,但是如果你把一个函数里面写上几百行的代码,各种hooks用到飞起的时候,你才会回过头来反思如何组织代码。如果Class能以一种更好/更易于理解的方式去抽象那为什么不用呢?
后/服务端框架的瓶颈
前端框架如此,基于Node.JS的后端框架也好不到哪儿去,难道你真的想用Express/Koa.js 去写大型的后端应用?这种量级的框架连web开发最简单的三层模型( 模型、视图、控制器)支持都不完整。当然你可能会说小型框架本来就只关注某一方面嘛,视图和模型层的东西可以用其它三方库解决。是的,确实可以这样,不过你不觉得Node.JS的第三方库有点太多了吗。正如NestJS在文档中提到的问题:很多JavaScript类库都没有高效地解决一个问题架构。React/Vue/Express/Koa这些都是相对独立的点,没有一个东西能把他们连接起来形成一个面,形成一种框架级别的体系。这就是架构的问题
这里多说一点,结合上面Java构建出来的生态,对比Node.JS的话。我借用自己打过的比喻:如果你低头看到的是Node.JS,那么你抬头未必能看见Java。假如你从事前端开发两三年后遇到瓶颈,想转学Node.JS,你会学习Exporess/Koa这类框架,但是很快你就会发现一个严重的问题:没办法深入下去了。因为当你用Express写完一个页面后就面临着各种技术上的盲点,会让你无所适从。
我也尝试绘制一张我对JavaScript/Node.JS或者说大前端体系理解的一张图:
JavaScript体系看似前后端通吃,客户端、 服务端甚至桌面端皆有。但是最大的问题在于:没有一个东西能给他们建立起关系并发展成为一种体系。
插播一条娱乐看点,前两天写 Ruby on rails 框架的作者 DHH 发推并配图:
大意是:现在的年轻人在web开发的时候是这样的嘛?底层逻辑、纯手写连接池 + 纯手工SQL、配置文件都放在了一起。天哪!(截图中使用的式TJ大神写的Express框架),然后TJ大神也回复了:
大意是:只有菜鸟玩家才能写出干净、简洁、高性能(黑Ruby性能)、见名知意的SQL,而不是去写一个有15层的抽象。两者的推特对话挺有意思,大家娱乐一下。
TypeScript 的瓶颈
TypeScript也主流,但是持续关注TS到现在,我发现TS也遇到了瓶颈,这个瓶颈不仅来自于TS的设计目标与理念,更多的还是社区及TC39。TS的设计初衷是 JavaScript的超集,由于本身要编译成JS,这一点本质上限制了TypeScript的方向,设计者对于添加一个新特性会非常谨慎,一者怕与TC39 ES proposal冲突,二者要考编译到不同版本JavaScript的兼容性问题。以至于现在TS新的语言特性只会跟进TC 39发布的最新ES proposal。但是我个人对于TC 39的效率及未来持怀疑态度,decorator的提案一直还处于Stage 2的阶段,像这种其它语言都成为标配好几年的事情,现在JavaScript社区还在草案(stage-2)阶段。
▷▶ 普及下 ECMA 的标准的流程:
stage-1:前期设想
stage-2:正式提案(装饰器所在的阶段)
stage-3:实现候选
Stage-4:完成测试
各个浏览器 JS 引擎实现;TypeScript 实现
在这个问题上我认为其实也很好解决,开个脑洞:如果微软想借助编程语言一统浏览器和客户端是没有什么不可能的。并入TC39组织,开发真正属于 TypeScript的原生引擎,奉天子以令不臣的方式也未尝不可。
近几年Microsoft对于开源的投入是肉眼可见的,微软要发力我相信很多东西都会有翻天覆地的变化。
打包工具的瓶颈
Webpack/Babel就更不用说了,主流中的主流。但是也是问题最严重的一个。Webpack/Babel的流行恰恰从反面证明了前端的基础设施有多么的烂。现在国外网友老天天叫喊着Webpack/Babel is eval也是挺值得深思的。我们引入了一个新工具来解决问题,却又在不经意之间产生了新问题。
前端构建工具问题的本质还是在于Node.JS的包管理工具的设计。这一点在Node.JS的作者Ryan Dahl关于Deno演讲《10 Things I Regret About Node.js》中也有过官方的承认。我相信任何一个实现过构建工具的人都被Node gyp打败过。node-sass, fsevent的痛不必细说。更不用说万年被黑的 node_modules了,你根本不知道一个简单的npm install命令会导致安装成千上万个npm包被安装到你的机器上。
当然每种编程语言对应的包管理工具都要解决依赖问题,而且这是一个普遍的问题,脚本/解释型编程语言尤为突出,Python/Ruby/PHP都有这些类似的问题。或许Go/Rust这种把源代码编译打包成单个可执行文件的方式才是好的解决方式。
从前人们总是抱怨JavaScript这门语言,黑它、讽刺它。但是我看到的是它在一点点变好。不仅是语言层面逐步完善,工具链生态日趋成熟,使用它的也人越来越多。大家对它的关注程度也在提高,整个JavaScript开发者的水平也在向更高更强的方向发展。生存环境只会淘汰那些老旧不再进化的事物,能适应变化的才会永存。
(1)几乎无所不在且不用安装,有浏览器就有JavaScript。脚本语言意味着它能被嵌入到任何宿主环境中去:Nginx、Native应用、硬件编程、物连网、嵌入式都有它的身影;
(2)这门语言对于技术的更新迭代有着强大的适应能力。JavaScript本身的更新迭代速度导致它进化速度很快,语言上的新特性很快被运用到生产环境。相比Python而言,这简直是做梦,Python2到3的转换没人能看到真正的时间表。
当下的前端开发状况不由得让我想起苏东坡《晁错论》中的一段话:天下之患,最不可为者,名为治平无事,而其实有不测之忧...。最大的问题在于,有些事物,从表面上看着平淡无奇,但实际上底层暗流涌动,似乎每一时刻都有着巨变的可能性。这也是前端开发最有趣也最有潜力的地方。
作为一名新时代的前端开发者,就是要在这看似风平浪静的表面之下,找到一些真正的突破点,兴许只是一个简单的想法,顺应时势然后造就出不斐的成就也说不定呢。无论是前端还是后端、国内还是国外,技术才是真正的核心竞争力,只有技术革新才能提高生产力,而对于我们程序员来讲,编程则是唯一能提升硬实力的方法。只要你心中充满了热情,坚持下去总会走出一条自己的路子。
我在2018年有幸参加了TypeScirpt的推广大会,TypeScript的作者Anders Hejlsberg亲自主讲。一位将近60岁的程序员在讲台上滔滔不绝的讲技术方案,TS的设计理念。你真的很难想像这样一位处于知天命阶段的老头子(实际上很年轻)讲的东西。
Q&A环节有个年轻小伙问:在中国做程序员很累、很难应该怎么坚持下去?(类似这样的描述,细节记不清楚了)的问题。Anders几乎毫不犹豫的说出了“Passion”这个单词。我瞬间就被打动了。在此之前我对于“激情”这个词的认识还停留在成功人士的演讲说辞层面,当Anders亲口说出Passion一词的时候,让人感觉真的是一字千金。直到现在Anders还作为TypeScript核心贡献者为它提交代码,到处奔走为TypeScript宣传。
我们再回到前端,那么未来的前端到底会发展成什么样?长期而言充满了未知数,谁也没法预测,但是短期来讲我比较关注几个东西:
(1)ESBuild :一个极快的JavaScript bundler。这个工具可以说是真正的「Game changer」。同样是一个打包任务,它快到让你没反应过来就完成任务了。ESBuild使用Go语言编写,实现了整套并行的ES解析器、代码生成器,作者是Figma的CTO(国外的 CTO 是要写代码的)。最近更新很频繁,Vue新的构建工具也会基于它来做TS部分的打包功能。
(2)Deno :一个安全的JavaScript&TypeScript运行时。Deno的方向充满了可能性,未来deno不仅仅可以做JS后端,还能和Rust打通,给JS注入一些原生native的能力,然后Webasmbly、webGL之类的技术都变成了可能,1.0 正式版发布日期也快到了。
(3)Figma:一个在线版的Sketch,虽然功能还没有Sketch强大,但是已经有了设计界面的基本能力。关键还在于它的整个实现都是基于web技术,底层C++实现图形的渲染、绘制,前端通过Webasmbly与浏览器Canvas交互,做到了让用户在浏览器端体验到了Native软件能力。像AutoLayout这种功能在用户体验上就是颠覆式的,使用的时候它很自然,没有什么存在感。但是用了就回不去了。
如果你仔细研究一番,上面的这些新鲜东西,都是起源于前端,但又不把视野局限在前端。或许这就是前端未来的发展方向吧。这几项技术将在后续文章中做详细阐述,敬请期待。【END】
关注技术说,我们只凭技术说话!
点在看会少个bug哦👇