【清明专刊】悼念逝去老友司徒正美,致敬曾改变世界的Flash
作者:互联网
熟悉本专栏的朋友们可能都了解,笔者CSDN的博客和公众号上的发文,基本上专注于金融数据库和芯片等一些偏后端的领域,不过去年笔者发了两篇纯前端的文章《两行代码引发的血案》和《Flash已死,Deno当立》,这两篇文章在CSDN公众号上发表以后,笔者甚至一直没有勇气点开链接多看一眼,因为这两篇基本都是为纪念司徒正美老师而写的。
我和司徒结识于CSDN,在2019年6月中旬当时在CSDN上看到一篇博文《前端开发 20 年变迁史》,心中不由赞叹,竟有人能将前端技术上升到哲学高度来进行阐释,于是千方百信找到了司徒的微信加为好友,和司徒聊天中,明显能感受到他对于前端技术的理解深度和积极热情。谁知天有不测风云,司徒年纪轻轻竟然溘然长逝,在此笔者也提示各位读者朋友们保重身份,切莫透支健康。
因此清明时节再发此文,一是纪念司徒老师,二是致敬那个曾经风靡一时的前端技术Flash,由于前端并不是笔者的领域,如有错漏还请各位读者批评指正。
只见新人笑,不见旧人哭的前端世界
去年年底微软正式全面移除了对于Flash的支持,无论是经典版的Edge(Spartan)、还是IE11都彻底告别了Flash插件。在早在2015年开始,谷歌的Chrome就开始逐步进行去Flash操作了,Flash的寿终正寝使这项在 PC 时代立下汗马功劳的互动动画技术,被H5这项新兴的前端技术彻底拍倒在岸上了。
今年3月2号deno1.8正式版发布了,Node.js之父Ryan Dahl 认为他在设计 Node.js 时犯一些包括安全性、package.json、node_modules等等一系列的错误,并表示这些bug 问题严重且不可回避,于是他在一系列的前端大会上都在怒怼Node,并在去年重新设计了 Deno 这门脚本语言。眼看着Flash和Node的滑落,也彻底浇灭了笔者这个门外汉想学习前端技术的热情,面对着变化莫测的技术栈,前端世界的程序员前浪们是不是太难了?
致敬-短视频和小游戏的共同始祖,曾经无比辉煌的Flash
Flash 诞生于 1990 年代初期,当时,FutureWave 推出了一款名为SmartSketch 图形软件,它使用触摸笔而不是键盘来操作。后来,FutureWave又将SmartSketch 重新设计成一款能在静态网页上插入动画和视频的工具,取名 FutureSplash Animator,它就是 Flash 的前身。
从90年代末到2006年左右,Flash获得了极速的发展,与目前所有IT培训机构都教Python的情况不同,当时的程序员如果不和人聊聊网页三剑客,简直出门都不好意思和人打招呼,而Flash作为三剑客中的绝对C位,风头一时无两。
说几个暴露年龄的梗,比如2003年一则Flash视频《大学生自习曲》突然红遍整个网络,据不完全统计在在其推出的一个月内,其播放量就突破了一亿次。而这可以说是短视频的始祖。后来如《东北人都是活雷锋》等神曲,也都为Flash火爆网络不断的增添动力。而且Flash也还是网页游戏的始祖,最早如《打飞机》、《超级赛车》等经典小游戏,也都是基于Flash的。可以说Flash能够争霸PC时代的一个重要原因,就是它极大的降低了制作动画的技术门槛,使得创意产业得到了极大的发展,当时各大广告公司将 Flash 视为非常重要的工具。在2006年之前Flash一直被认为会是互联网上“永恒的存在”,
成败皆插件
Flash特别适用于低速互联网的内容,因为它的文件非常小。Flash是通过广泛使用矢量图形做到这一点的。与位图图形相比,矢量图形需要的内存和存储空间小很多,因为它们是以数学公式而不是大型数据集来表示的。我们可以看到一般来讲Flash每分钟动画的大小一般不到1M,远比目前的高清视频小得多。可以说体积小,用户体验却很高的优势,正是Flash在十几年前称霸互联网的不二法门。
而也正是因为放弃使用普通的图片格式而使用知量图形,这使得Flash并不是浏览器原生的。矢量图的渲染Flash的浏览器插件的运行效率并不高,而且访问电脑资源也很不方便,导致很多程序员在开发的过程中出现许多的问题,就算成功发布了一款 Flash 应用,浏览器也会被 Flash 插件拖得很慢,电脑会因此变得很卡,所以 H5 技术出现后,很多人就开始转投到转而开发基于H5的互动技术,并开发出了如Hilo等新型互动框架。不过凭心而论Hilo其实并不是Flash的终结者,一切都在IPhone开启了移动时代之后全部都变了。
错失移动时代的Flash
2007 年,苹果推出了初代 iPhone,Adobe 的工程师自然也很快地接受并使用了它。iPhone 的出现给 Adobe 移动端开发带来了问题:Flash插件运行的缺点,被无限放大了,由于Flash日益臃肿,需要大量计算资源才能支持其动画的渲染,这在 PC 端并没有问题,而在手机端,Flash的运行需要消耗大量的电力,但手机的电池有限,以至于苹果选择不支持 Flash。Flash 需要重新开发才能适应 iPhone,然而 Adobe 并未能和苹果达成最终的合作协议。这个决定为苹果招来了不少批评,人们认为乔布斯不支持 Flash 反应了苹果的封闭。为此,乔布斯在 2010 年发表了一封公开信,表示“iPad 永远不会支持 Flash”,并指出了 Flash 的问题:耗电严重、安全漏洞多,不适合苹果的移动系统。
苹果的表态之后,视频生态开始转向,YouTube 等网站开始采用基于开放标准的免费软件,这种技术既适合桌面端也适合移动端。2014 年10 月制定的 HTML5 标准也成为 Flash 的替代品被广泛使用,它让网站在没有插件的情况下运行视频和动画。而 Adobe 自身也认为,Flash 对该公司的业务不太重要。Adobe CEO Shantanu Narayen 表示,现在,Flash 仅占 Adobe 营收总额的一小部分。因此也没有对Flash进行持续进行输血,这也加速了Flash的落漠。
同样也是由于Flash插件运行缺点,使其近年来频繁爆出安全漏洞,这无疑给 Flash 带来了更大的打击,Gartner高管Danny Brian 在2014年就曾表示,Flash 的消亡已经不可避免。
Node之父反出Node,问题出在哪里
去年底,Node.js之父Ryan Dahl在柏林JS大会上发表了题为“Design Mistake in Node”的主题演讲,并提出“Node失误太多无法回避,Deno前景明朗”其中Deno就是Node的反写,其也有内涵反Node的意味,目前看Node与Deno的主要参数比较如下:
项目 | Node | Deno |
入口 | package.json配置 | import url 直接引入 |
API 引入方式 | 模块引入 | 全局对象 |
安全 | 无安全限制 | 默认安全 |
Typescript | 第三方,如通过 ts-node 支持 | 原生支持 |
包管理 | npm + node_modules | 原生支持 |
异步操作 | 回调 | 原生支持Promise |
包分发 | 中心化 npmjs.com | 去中心化 import url |
打包、测试、格式 | 第三方eslint、gulp、webpack、babel | 原生支持 |
我们看到Node.js并不能像Deno一样原生支持异步操作,这还在去年年中引发了一场大规模的“血案”,在is-promise(npm地址:https://www.npmjs.com/package/p-is-promise,Githubf地址:https://github.com/sindresorhus/p-is-promise)更新后,超过300万个引用了该模块的前端项目均出现了问题,甚至让整个 JavaScript 生态系统陷入了混乱。
Node.js中需要通过promise机制实现异步回调功能。而根据MDN上对于Promise机制的描述(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise),Promise对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象。示例及注释如下:
//创建一个Promise对象,定义resolve方法,在3000ms后执行。
const promise1 = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('promise');
}, 3000);
});
//非阻塞执行promise1,在promise完成后此方法会被执行。
promise1.then(function(value) {
console.log(value);
// 3s后会输出promise
});
console.log(promise1);
//直接输出 [object Promise]
而本次出现问题的is-promise包,就是用来测试一个JavaScript对象是否为Promise的。is-promise包的代码其实非常短,其主要的功能实现代码只有两行而已。前端开发人员在引入is-promise包之后,就能在自己的项目中引用它,而且is-promise包是基于MIT协议的,因此引用该项目,也不必须要求开源。虽然只有两行代码,但is-promise 库却是当今最受欢迎的 JavaScript 软件包之一。据不完全核计is-promise是700余个知名的JavaScript 库的依赖项,其影响项目数量至少超过300万,范围涵盖至封闭源 JavaScript 代码库和 JavaScript 生态系统中一些最大的项目。其中包括有:Facebook 的 Create React App(用于创建 React 应用程序的标准模板)、谷歌的 Angular.js 框架、谷歌的 Firebasse-tools、亚马逊的 AWS Serverless CLI、Nuxt.js 和 AVA 等。
is-promise 库之所以引发问题,关键在于他没有遵循正确的ES模块标准,而提到ES模块标准,我们还要从最基本的概念聊起。我们知道JavaScript是一门动态的脚本化的语言,它使得前端页面的开发变得非常简单。JavaScript的编程范式抽象成维护变量,赋值和计算操作。大量的代码在用于操作变量,开发者需要懂得如何去组织和维护这些变量。JavaScript 提供了一种方式,即函数作用域。在一个函数内只需要考虑这个函数的变量问题。不必去担心其他函数会操作这些变量。当然,随之带来的问题是,变量无法共享,无法在不同的函数之间相互共享变量。如 果想要在作用域外共享变量,只能通过外层作用域,或者全局作用域。
而ES模块标准,则提供了更好的方式来组织变量和函数,把相关的变量和函数组织到一起。具体就是将这些函数和变量放到一个模块作用域内,实现在模块间共享变量。与函数作用域不同的是,模块内部的变量实现了在其他模块内共享。而且可以指定哪些变量、类或者函数可以共享。在其他模块中共享,被称为 export。这就出现了模块间的依赖,是一种很明确的关系,当移除一个模块时可以准确的知道哪些模块会出错。一旦有了模块间导出和引用变量的能力,我们就可以将代码打成小包。然后就可以像乐高玩具那样组合,再组合。使用小模块就可以创建出各类应用。在使用模块的时候,其实就是在做一个依赖关系图。ESM的模块包括三个过程:
1:构建:下载,解析,然后把文件解析为模块记录
2:实例化:为模块分内存空间(此时还没赋值),然后依照导入,导出语句把模块指向内存地址,这个过程叫链接
3:运行(求值):运行代码的时候,才会给内存空间填充真实的值
而ES则通过一系列的标准来确保相关代码可以实现上述模块化的功能。
is-promise v.2.2.0 版本却未遵循正确的 ES 模块标准。因此在其更新发布后,引用了is-promise在各个项目都在的构建链时出现了问题。
后记
从Flash和Deno的情况可以看出,互联网世界曾经的繁荣真的不能代表未来可以一直高枕无忧,就像Flash一样,曾经红极一时的霸主也难逃最终的落莫结局,不过笔者看到程序员对于这种变化却是比较乐观,最后笔者引用司徒老师的名言做结“当初JavaScript被误解为最糟糕的语言,时至今日它是最流行的语言,GitHub 60%的项目都是与JavaScript有关。任何可以使用JavaScript来编写的应用,最终会由JavaScript编写。”愿前端开发之路越来越好!
标签:Node,JavaScript,正美,Flash,专刊,promise,模块,变量 来源: https://blog.csdn.net/BEYONDMA/article/details/115412820