这些年,前端发生了颠覆性的变革,这种变化极大地改变了前端的生态,前端从很多年前一个不起眼的角色跨步式的演变为一个不可或缺的存在。
前端的技术不仅是在前端开发本身,它的触角伸向移动开发,后端开发。如果要评选一种全栈式的技术,那后端,移动端本身的一些技术是无法与前端相抗衡的。
前端已今非昔比!
但是,由于我个人从事了很多年的后端与移动端的开发,在将前端的现状与后端移动端等做对比后,我仍然觉得前端存在一些它自身需要突破的困境。
本周,继续就前端阐述自己的思考与分析,这是前端之变系列文章的第七篇,前六篇分别是:
- 前端之变(一):技术的变与不变
- 前端之变(二): "不变"的前端
- 前端之变(三):变革与突破
- 前端之变(四):进击的前端
- 前端之变(五):王者归来
- 前端之变(六):引领式变革,从命令式UI到声明式UI
写在最开始的话
由于是讲前端的困境,所以我希望能做一个简单的申明:
- 前端技术的发展是很快的,本身是非常出色的,这篇文章说的问题,并不是我个人对它的否定,只是基于我个人的全栈式的技术背景下的一些思考
- 这些只是个人的思考,它当然有大概率是错误或偏颇的,但阐述个人的意见也是一件有价值的事。
- 下一篇,我会讲到相反的一面,就是对前端未来发展的一些思考,在那里,会分析前端具备的优势及对前端技术发展前景的一些预测
三个维度的问题
在思考与整理前端的问题,我把它归纳为三个维度,我认为这三个维度的问题是前端技术需要着力改进的,一旦这些得到改进,前端的未来不可小觑
我分析与总结前端面临的困境,归纳起来就是:
- 语言之困
- 生态之困
- 开发者之困
接下来,我会逐一阐述我的思考
语言之困
JavaScript
前端语言的核心是JavaScript,想必这个大家都没有意见。
基于我使用过Java,OC,Kotlin,还有前端的TypeScript等语言,将JavaScript语言与这些相比,我可以很轻易的下一个结论:
JavaScript远称不上是一个优秀的语言
JavaScript是10天设计及开发出来的,网景公司最开始的目标是"设计一种与Java足够相似又更简单的语言",但JavaScript的设计者对Java并不是很认可,更偏向函数式风格的设计风格,于是在这种情况下,JavaScript诞生了。
它结合了设计者喜欢的面向函数式的一些风格,又不得不遵照公司的要求,让它与Java有点相似,具备面向对象的一些风格。它的设计者并不是非常喜欢它,以致于说了"与其说我爱Javascript,不如说我恨它。它是C语言和Self语言一夜情的产物"这样一句话。
关于JavaScript的语言设计缺陷,在《javascript语言精粹》书中有比较多的阐述。这篇文章我不详细阐述这些。
可想而知,无论今天javascript的应用范围有多广,这改变不了一个显著的事实。
一个优秀的语言更容易产生优秀可维护的代码,而不好的语言,则会困难很多。
而几乎整个前端生态都建立在JavaScript之上。
不能不说,这是前端的一大困境,就算是在TypeScript出现之后,很多有名的框架都在转向TypeScript,但JavaScript对前端的影响仍将一直存在。
TypeScript
说完JavaScript,我就不得不说前端的另一门语言:TypeScript
想必微软之所以要设计另一种语言,与JavaScript自身所带的问题也有很大的关联。不管如何,一门能取代JavaScript的新的前端语言TypeScript出现了。
与JavaScript这种四不像相比,TypeScript与Java更相似。
在这里我贴一段我的Java代码与Typescript代码以作对比。
TypeScript
代码语言:javascript复制 public async fetchUnconfirm(): Promise<number> {
const fetchUrl = Config.getInstance().api "/bings/" BingMessage.tagString(BingTag.Unconfirm) "?skip=0&limit=0";
const response: BaseResponse = await this.request.requestForGet(fetchUrl);
if (response.resultSuccess()) {
return response.result.total_count;
}
return -1;
}
Java
代码语言:javascript复制 public Goods addGoods(){
this.created = System.currentTimeMillis();
Goods goods = getGoodsRepository().addGoods(this);
getItemRepository().createInventoryItemFromGoods(goods.getId());
return goods;
}
可以看出,TypeScript与Java更类似,可以说TypeScript是一门面向对象的语言。
TypeScript远比JavaScript优秀,更像一门现代语言,但TypeScript在现在的前端也面临着一些问题
- 它毕竟是依赖于JavaScript的,它无法取代或消除JavaScript,只能共存
- 它只适合于一些使用了Node环境的场景,如果你不是用的npm及node来做前端,比如用的纯JS或JQuery,除了JavaScript,你别无选择
- 很多前端程序员对TypeScript的理解停留在它是一个带Type的JavaScript,我不只一次的见过许多人将Flow与TypeScrip相提并论,因为Flow也是给javaScript提供Type支持。大多数前端人员对TypeScript带来的面向对象的编程思维要不就是不太理解,要不就是视而不见。
生态之困
在『后』前端时代,前端也出现了npm包管理,这与后端Java的maven依赖如出一辙。
npm上的包的数量巨多,我一开始也没意识到它存在的问题,直至我使用了awesome-typescript-loader这个依赖之后,我才慢慢意识到前端的生态是存在一些问题的。
起源
基于electron的跨平台应用
我在2020年做PCX的时候,用的是typescript 3 webpack 4 react 16 mbox 5的整体技术架构,其中webpack用来转换ts的插件就是awesome-typescript-loader,当然,还有ts-loader,以及babel也能转换ts代码。
ts-loader是webpack官方文档中推荐的搭配。
我之所以会用awesome-typescript-loader,原因在于我在typescript官方博客或其它博客(印象不深刻了)上,它们推荐了awesome-typescript-loader这个,并列举了awesome-typescript-loader比ts-loader优秀在哪的一些原因,基于这个原因,我在项目中选择了awesome-typescript-loader。
这是很正常的一件事,事实上,它也一直运作的比较正常。
直到...
问题
2021年,我在整理myddd-electron,准备把pcx的几个核心依赖进行升级,升级为webpack 5 typescript 4 mbox 6 electron 12等,升级完后,其它的都还比较正常,但awesome-typescript-loader遇到问题了。
它始终有问题,我非常奇怪,我想着是不是要升级新版本,然后我去npm官网查找了下,希望升级到最新版本,支持typescript 4以及webpack 5的版本。
我看到的是这种情况:
这个框架,早在3年就就停止更新了。
当然,这个问题以我切换使用ts-loader而解决。
我扫了一下,这个问题还不只是个案,我使用的ioc框架--typescript ioc也停止更新了,后面不得已我又切换到微软的tsyringe而解决。
我觉得很惊奇,因为在Java我从未遇上类似的情况,可能很多前端程序员不太清楚,但我可以明白无误的告诉前端开发者:
在Java的主流依赖中,没有任何一个框架,会长时间不更新,几乎没有出现类似的情况
调查与思考
基于这种情况,我稍微调查了下前端的生态,再结合与Java的生态相比,我发现前端的生态有很多明显的问题,表现在:
生态以个人开发为主
Java的主流生态,无论是Spring,或是hibernate,或是Vert.x等任何一个主流的被程序员使用的框架或类库,几乎无一例外后面是由一个公司或基金会在支撑运营,当然它们大多也是开源运作的。
而前端的许多生态,基本上是个人开发者为主,比如著名的webpack,最开始几乎是以一个开发者做的,后面是出名了后,很多个人开发者添加插件,才形成现在的局面。但它直至现在,依然是由这个开发者在主导。还有类似上面我说的awesome-typescript-loader,ts-loader等,都几乎是属于个人开发者的产物。
我不是批评这种个人开发的生态,它在某种程度上是前端生态能迅速发展的一个优势所在,但我想说的,与后端的一个明显的区别在于:后端的生态使用的主流的技术,基本上都是公司在背后支撑,它们的质量与可靠性,更新的及时性,的确远优于个人开发者。
个人开发没问题,但往上是不是应该自然而然的提升至公司或开源基金会?这是前端生态不得不面临的挑战之一。
从另一个角度来对比,typescript,react这些都是由大公司主导的开源,可以看到,它们的更新及时,可靠性有保障。我想程序员在使用typescript或react时,应该较少怀疑到它们会有很多问题,或会有一天没人更新了吧?
框架各自为战,没有形成标准
我在做pcx时,在针对ioc与数据库两个方面,我在寻找合适的框架来处理它。
可能很多前端程序员压根不清楚IOC是什么,这一点我在后面的开发者之困会再讲到这一点。
"控制反转(英语:Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。"
在后端Java的生态中,无论是IOC或是数据库ORM,虽然最开始都是各有不同的框架诞生,但很快,由于它们的重要性及普及性,标准便诞生了。在ORM数据库方面诞生了JPA标准,而在IOC,Java添加了IOC的标准annotaion,而具体的一些框架,后面都遵守这个标准,是这个标准的实现。
但很可惜,在前端,无论是IOC还是ORM数据库,无一不是各自为战,每个框架有自己的一套标准与概念,互不相通。
IOC我调研过typescript-ioc,inversifyjs,后面在typescript-ioc不适配typescript4后,我又发现了微软的tsyringe,考虑到它是微软的东西,质量肯定有所保证,我毫不犹豫的使用了它。它们之间没有任何共通之处。
而orm数据库方面,有Sequelize,TypeORM等,但它们同样几乎没有任何相通之处。每种框架都有自己的风格与模式。
缺少顶级的开源基金会
做java的程序员,不可能不知道apache基金会。
apache基金会代表了开源框架质量控制的一种最高生态,它是一种顶级开源基金会,只有质量极为可靠,有保障的开源框架才能纳入apahe开源基金会,比如国内阿里公司前些年的dubbo开源框架,因为依靠阿里的强大技术实力,这个框架在国内中小企业早就使用非常广,但就算是如此,它也是在流行很多年后,才申请并被批准进入apache基金会的。
很可惜的是,前端并没有类似的基金会。总体还是一些大公司主导的类似React的框架与广大个人开发者的开源作品混合的一种生态。
由于有公司,有基金会的支持与管控,后端主流的框架,几乎不会出现不更新的情况,我几乎没有遇上类似的情况。
而前端相比,生态的确还有差距,Java的生态运作方式很值得前端借鉴与学习的。
开发者之困
我在前面讲到IOC时,我做了一个断言:可能很多前端程序员不太清楚IOC是什么。
这便是我要讲的困境的第三点:开发者之困
我认为一个显而易见的事实是:前端程序员对面向对象编码理念的理解远逊于后端程序员
当然,这并不是前端程序员的问题,由于前端是以JavaScript起家,JavaScript怎么说都不能说是一门面向对象的语言,自然而然前端程序员对面向对象的编码理念并不太知情,也是理所当然的。
与前端程序员不同,后端程序员不管有意还是无意,几乎在编码生涯的一开始,就能遇到一些面向对象的理念,比如:
- 面向对象的基本特性:封装,继承,多态
- 解耦的关键方式:IOC依赖注入
- 面向接口编程,而不是面向实现编程
- MVC模式,分层等
等等
并不是一定有人在刻意教导后端程序员这些理念,关键是后端程序使用的框架从一开始就是这样倡导的,比如我刚毕业时,后端当时流行的是SSH架构,也就Spring Struts Hibernate的一种技术搭配,
在这种搭配中,本身就带有一些理念
- SSH是MVC模式的一种实现
- Spring负责IOC,也就是依赖注入
以下这些理念,对后端程序员来说,它们是最熟悉的,移动端程序员次之,而我认为前端程序员的理解就属于最差的了:
- 面向对象语言的基本特性:封装,继承,多态
- 面向对象的五大基本原则:单一职责原则,开闭原则,里氏替换原则,接口隔离原则,依赖倒转原则
- 二十多种常见的设计模式:单例模式,观察式模式,工厂模式,适配器模式,模板模式等
- 常见的架构风格:MVC模式,分层模式,领域驱动设计风格,六边形架构等
- 测试驱动理念,重构理念,敏捷软件开发理念等
以上这些,决定了代码质量好坏,可维护性的一些基本原则与理念,可以说前端程序员对它们的熟悉情况可能是三个技术方向中最差的,从根本上说也是因为前端本质是由JavaScript驱动的原因导致的。
而JavaScript并不能算是面向对象的语言。
以致于在TypeScript出现后,很多前端程序员仍然把它当作另一个Flow,把它视为带Type的JavaScript,
TypeScript不是带来了Type这么简单的事,很多前端程序员没有理解到,TypeScript更重要的意义在于,它给前端带来了面向对象的一整套优秀理念与模式,使得前端终于能够跨入面向对象的世界。
而面向对象的上面这些理念,仍然是当今我们程序世界最优秀的理念,虽然近些年函数式有越来越流行的趋势,但就理念上来说,面向对象的这些概念与理念,仍然是最好地能带来优秀的,可维护的代码的原则与理念。
这就是为什么几乎现在所有技术方向的所有语言,都是由面向对象语言主导的原因所在,后端的Java,移动端的Kotlin,Swift,OC,前端的TypeScript,它们几乎无一例外的属于面向对象的语言。
而我们前端的程序员,必须要去学习现理解这些优秀的理念。
前端的未来
虽然有我说的这些困境,但前端的变化仍然是瑕不掩瑜的,今天唯有前端的技术,最接近全栈式编码的可能。类似我这种,又搞过后端,又搞过移动端,又搞过前端终究是少数。
很多年前,有一位程序员说过一句话:
Atwood's Law: Any application that can be written in JavaScript, will eventually be written in JavaScript. 任何可以用 JavaScript 来写的应用,最终都将用 JavaScript 来写。
这是事实吗?它会是前端的未来么?它会成为我们的编程的未来么?
下一篇,前端之变的最终篇:前端之变(终):前端的未来。阐述我对前端未来发展的一些个人的思考。