前端开发的瓶颈在哪里?前端技术走到十字路口了吗?全栈系统架构能否改变目前的困境?本文将结合自己的开发经验,谈谈当前前端开发中遇到的一些问题和想法。Introduction我这两年一直在思考的一个问题:如果前端不需要考虑性能问题,终端兼容性,历史遗留问题,甚至具体的技术实现……如果我们假设我们有丰富的技术储备,不使用综合以上问题,前端到底能做出什么样有价值的东西?让我们把时间拉回到5年前……如果你“那时”还在做前端开发的话。上述问题肯定是您必须面对的典型问题。甚至前端开发在当时的意义。你会为了准确还原设计稿而熬夜加班,练就一双像素眼;你将研究解决几个字节的性能问题的优化方案,甚至理解每一个HTTP请求头;你也会因为一些技术问题跟同事理论,最后达到产品喋喋不休的境界;但是随着时间的推移,前端技术的更新迭代,以及互联网的发展。你会发现,这些过去的问题似乎不再是问题,或者在可预见的未来可能都不是问题。页面加载性能可能不再是问题。借助HTTP2技术、5G基础设施和更快的硬盘驱动器。兼容性问题逐渐淡出了大家的视野。Chrome独一份,微软不得不向它靠拢。很多前端开发人员已经具备后端(或多端)技术能力,技术储备未必是问题,当然前提是你能招到人。定义什么是前端开发,前端和后端的界限在哪里?我三年前定义的:前端负责界面和交互展示;后端负责数据和业务逻辑;但是现在好像已经过时了,越来越觉得不应该有这么清晰的边界把前后端分开,尤其是在技术层面(除了功能层面的边界有利于协作)。这就好像在说:如果你不能打破规则,你就注定要被规则束缚。我一直认为,程序员应该有比常人更快地适应新技术、新工具、新概念的能力。举个简单的例子,我以前写代码用tabs缩进,然后大家建议用空格。一开始我是绝对拒绝改成空格的,因为人的习惯是很难改变的。但是当你真正为改变而实践时,你往往会找到一条新的路。还有要不要加分号的问题。现在回过头来看,前端在整个系统层面所起的作用,至少应该是在整个View层面。视图层的技术更贴近软件系统的上层,更具有感性。感性的东西就是说一个颜色,我觉得好看,他觉得不好看,完全是个人情调。所以前端更关注UI、交互以及整个产品层面需要解决的问题。优秀的前端一定要有敏锐的产品洞察力。当然,这只是前端最基本的职责。同时,前端是离产品最近的技术角色,技术才是前端真正的硬实力。大约在去年,我的职位从前端转到了后端Java程序员的角色。虽然我只做了一年的Java程序员,却是我自己技术提升最多的一年。大家可能普遍认为从后端转前端比较容易,从前端转后端会有一个门槛。其实根据我自己的经验,并不是这样的。Java语言是一种商业化、成熟的语言。无论是语言本身,还是周边的框架和工具,都有一套非常成熟、层次分明的系统抽象。如果你有两三年的编程经验,你很容易突然转向Java,尤其是Javaweb。Spring框架为程序员屏蔽了很多复杂的问题,事实上已经成为各大互联网公司的主流框架选择。我特意按照自己的学习路线画了一个Java版程序员的学习路线,仅供参考:我们可以清楚的看到Java构建的整个系统最大的特点:循序渐进,循序渐进。建立正面引导。当我在应用层阶段,我需要关心的只是一些概念和方法。有了基础之后,我就可以上手Spring框架了。servlet出现在您的视野中。上学的时候看不懂java中Servlet的概念,后来参加工作后又学习了一些Python。再次看到Java中的Servlet,立马明白是Python中的uwsgi,是一个接口。与服务器网关相关联的规范。然后就可以顺利进入下一个环节,服务器/通信。在这里你会发现Socket,它是整个网络编程的核心。你在学校的时候并没有理解Socket的概念。继续学习,你就会明白,Socket其实是操作系统提供给编程语言的一种能力。有了它,你就可以建立一个服务器与客户端通信。在这个链接中,您将学习网络层的TCP/IP协议,并了解TCP/UDP之间的区别。而(true){socket.listen()}会在设置Socket监听的时候造成性能问题,那么接下来你将进入抽象层次、操作系统和计算机原理。为了解决“whiletrue”监听连接的性能问题,你将学习多线程技术并理解并发的概念。您可能一直听到人们讨论并发和并行之间的区别。继续学习之后,你会逐渐明白:并发多是用来解决网络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能做好,自己做不好,那就不是选择的问题了。PixiJS6已经在为2D游戏/绘图设计了,我个人认为最好不要玩3D。这些看似成熟的系统其实还有很多值得探索的地方。如果不深入研究,你可能会认为两年后,这些技术就会稳定前端,达到大一统的状态。这种想法可能太天真了。我举个例子说明一下他们各自的瓶颈:React(不是特指React),前端/客户端框架的瓶颈,虽然现在看起来是主流,但是还有很多问题没有解决。甚至可以说是无解。React的本质只是一个UI库,而不是一个框架。框架要解决的问题是系统层面的,而不是抽象层面的。用React写过几个项目后,你会发现用React写大型项目是很麻烦的。React本身并没有解决SPA应用中数据流的问题,甚至没有解决状态管理的问题(或者说状态管理是个伪命题?)。一个非常简单的父子组件之间的状态共享问题还没有得到成熟的解决。钩子的解决方法更像是拆东墙补西墙。而现在React社区弥漫着一种鼓吹函数式编程的邪气,hooks更像是一块遮羞布。大部分人之所以用hooks,只是不想用Class,因为Class臃肿,功能更简单。这个逻辑当然没问题。功能真的很简单,但是如果一个函数写了几百行代码,各种钩子飞的时候,你会回过头来反思如何组织代码。如果可以以更好/更简单的方式抽象类,那为什么不呢?后端/服务器框架的瓶颈是前端框架,基于Node.JS的后端框架也好不到哪儿去。你真的要用Express/Koa.js写大型后端应用吗?这种规模的框架甚至不支持Web开发最简单的三层模型(模型、视图、控制器)。当然,你可能会说小框架只专注于一方面,view和model层可以通过其他三方库来解决。是的,这是可能的,但你不觉得Node.JS有太多的第三方库吗?正如NestJS在文档中提到的一个问题,“很多JavaScript库并没有高效地解决一个问题架构”。React/Vue/Express/Koa是相对独立的点,没有什么可以把它们连接起来形成一个面,形成一个框架级的系统。这是架构的问题。这里再多说一点,结合上面Java搭建的生态,和Node.JS对比一下。借用我打过的一个比方:如果你低头看到的是Node.JS,那你抬头可能就看不到Java了。如果你2、3年的前端开发遇到瓶颈,想转Node.JS,你会学习Exporess/Koa等框架,但很快你会发现一个严重的问题:无路可走更深。因为当你用Express写完一个页面后,会面临各种技术盲点,让你无所适从。我也试着画一张我对JavaScript/Node.JS或者大前端系统的理解:JavaScript系统好像包揽了前后端所有,包括客户端,服务端甚至桌面。但最大的问题是:没有什么可以为他们建立关系,发展成系统。插个娱乐点,前两天写Rubyonrailsframework的作者DHH发推配图:大意如下:这就是年轻人做web开发时的做法吗?底层逻辑,纯手写连接池+纯手工SQL,配置文件都放在一起。上帝!(截图用的是TJ大神写的Express框架)然后TJ大神也回复了:大体思路是这样的:只有菜鸟才会写的干净,简洁,高性能(黑Ruby性能),众所周知的SQL,不是Go写一个15层的抽象。两人的推特对话很有意思,请大家玩得开心。TypeScript语言的瓶颈TypeScript也是主流,但是持续关注TS到现在,发现TS也遇到了瓶颈。这个瓶颈不仅仅来自于TS的设计目标和理念,更多的是来自于社区和TC39。TS的设计初衷是JavaScript的超集。由于需要编译成JS,这从本质上限制了TypeScript的发展方向。设计人员在添加新功能时会非常谨慎。一是怕和TC39ES提案冲突。检查编译为不同版本的JavaScript的兼容性问题。所以现在TS的新语言特性只会跟进TC39发布的最新ES提案。不过,我个人对TC39的效率和未来持怀疑态度。decorator提案仍处于Stage2阶段。像这样的其他语言已经成为标准好几年了,而JavaScript社区仍在起草它(stage-2)阶段。普及ECMA的标准流程:stage-1:初步构想stage-2:正式提案(装饰器所在阶段)stage-3:实现候选Stage-4:完成各个浏览器JS引擎实现的测试;TypeScriptimplementationishere就问题而言,我觉得其实很容易解决。让我敞开心扉:如果微软想用编程语言来统一浏览器和客户端,没有什么不可能的。融入TC39组织,开发真正属于TypeScript的原生引擎,听从皇帝的命令也不是不可以。近年来,微软对开源的投入是肉眼可见的。如果微软要努力,相信很多事情都会发生翻天覆地的变化。Webpack/Babel就更不用说了,打包工具的瓶颈,主流中的主流。但这也是最有问题的。Webpack/Babel的火爆恰恰从反面证明了前端基础设施有多么糟糕。现在国外网友每天都在喊,Webpack/Babeliseval也值得深思。我们引入了一种解决问题的新工具,却无意中创造了新的问题。前端构建工具问题的本质在于Node.JS包管理工具的设计。这在Node.JS作者RyanDahl关于Deno《10 Things I Regret About Node.js》的演讲中也得到了“官方”承认。我相信任何实现过构建工具的人都被Nodegyp打败过。node-sass和fsevent的痛点就不用细说了。更不用说已经被黑了几千年的node_modules,你根本不知道一个简单的npminstall命令会导致你的机器上安装上千个npm包。当然,每种编程语言对应的包管理工具都必须解决依赖问题,这是一个普遍的问题,尤其是脚本/解释型编程语言,Python/Ruby/PHP都有类似的问题。或许Go/Rust将源代码编译打包成单个可执行文件的方式是一个很好的解决方案。过去,人们总是抱怨JavaScript语言,黑它,讽刺它。但我看到的是,它正在一点一点地变好。不仅语言水平逐渐提升,工具链生态也越来越成熟,使用的人也越来越多。大家对它的关注度也越来越高,整个JavaScript开发者的水平也在往更高更强的方向发展。生存环境只会淘汰那些陈旧的、不再进化的东西,而那些能适应变化的东西,就会永存。JavaScript是一种具有其他编程语言所没有的两个优点的语言:它几乎无处不在并且不需要安装。JavaScript在浏览器中可用。脚本语言意味着它可以嵌入任何主机环境:Nginx、Native应用、硬件编程、物联网、嵌入式系统都有它的身影。这种语言对技术更新和迭代具有很强的适应性。JavaScript本身的更新迭代速度导致其快速演进,新的语言特性会很快应用到生产环境中。与Python相比,这是一个梦想,没有人能看到Python2到3过渡的真实时间表。现在的前端开发形势不禁让我想起了苏东坡的一段话《晁错论》:世间的烦恼,最不能接受的,叫做太平盛世,其实有意想不到的烦恼……最大的问题是,有些事情,从表面上看,看似平淡无奇,但实际上,暗流涌动,似乎每时每刻都有大变的可能。这也是前端开发最有趣、最有潜力的地方。作为新时代的前端开发者,有必要在这看似平静的表面下找到一些真正的突破点。可能只是一个简单的想法,也有可能顺势而为,成就一番伟业。无论是前端还是后端,国内还是国外,技术才是真正的核心竞争力。只有技术创新才能提高生产力。对于我们程序员来说,编程是提高硬实力的唯一途径。只要心中充满热忱,坚持不懈,总会找到属于自己的路。分享一点经验,有幸参加了2018年的TypeScript推介会,TypeScript的作者AndersHejlsberg亲自做了演讲。一位年近六十的程序员在讲台上滔滔不绝地讲述着技术方案和TS的设计理念。你真的很难想象这样一个“知天命”阶段的老人(其实很年轻)在说什么。在QA环节,一个小伙子问Anders“在中国做程序员很累,很难坚持下去(这样的描述,具体记不清了)”。安德斯几乎是毫不犹豫的说出了“激情”这个词。我顿时被感动了。因为在那之前,我对“激情”这个词的理解还停留在成功人士的演讲层面。当安德斯自己说出激情这个词时,感觉就像一千个词。直到现在Anders都作为TypeScript的核心贡献者为其提交了代码,四处奔走推广TypeScript。让我们回到前端,那么未来的前端会发展成什么样子呢?长期充满未知数,没有人能预测,但短期内我更关心一些事情:ESBuild:一个极快的JavaScript打包器。这个工具可以说是真正的“游戏规则改变者”。同样是打包任务,快到你还没反应过来就完成任务了。ESBuild使用Go语言编写,实现了一套完整的并行ES解析器和代码生成器。作者是Figma的CTO(没错,国外的CTO是要写代码的)。最近更新比较频繁,Vue新的构建工具也会基于它来做TS部分的打包功能。Deno:一个安全的JavaScript和TypeScript运行时。Deno的方向充满了可能性。未来,Deno不仅可以做JS后端,还可以和Rust对接,为JS注入一些原生的能力,然后Webasmbly、webGL等技术都成为可能,1.0正式版的发布日期也临近了。Figma:网络版的Sketch,虽然功能没有Sketch强大,但是已经具备了基本的界面设计能力。关键是它的整个实现都是基于web技术的。底层C++实现图形渲染和绘制。前端通过Webasmbly与浏览器Canvas交互,让用户在浏览器端体验Native软件能力。像AutoLayout这样的功能在用户体验上是颠覆性的。使用时非常自然,没有存在感。但是一旦用了就回不去了。细细研究的话,以上新事物都起源于前端,但并不局限于前端。或许这就是前端未来发展的方向。
