JavaScript 开发的历程:
一、史前时期
JavaScript 最初是在 1995 年发布的。就像我在前文所述,我是在 2012 年开始编写 JS 的,差不多也就是在 20 年后,新一代的框架刚刚开始成熟,比如 Angular.js、Ember.js、Backbone 等
jQuery 和 MooTools 这样的库,开发人员最常做的事情就是引入 jQuery,并为一些 UI 组件编写脚本
二、第一代框架
在 2000 年代末和 2010 年代初,第一代用于编写完整客户端应用的框架开始出现。这个时代著名的框架包括:
1.Backbone.js
2.Angular 1
3.Knockout.js
4.SproutCore
5.Ember.js
6.Meteor.js
这一代的框架正在试图进入一个未知的领域。一方面,它们要做的事情是很有野心的,很多人认为它们并不会成功。有许多的反对者认为单页 JS 应用(SPA)从根本上来讲是非常糟糕的,在很大程度上
大多数框架都在试图模仿其他平台上的流行做法,所以大多数的框架都经历了 Model-View-* 的变迁,如 Model-View-Controller、 Model-View-Producer、Model-View-ViewModel 等等。但从长远来看,这些都算不上真正有意义的工作,它们并不直观,而且很快就会变得非常复杂
开始尝试编译 JavaScript 应用的时代。2009 年,Node.js 发布,2010 年 NPM ,它们为(服务器端)的 JavaScript 引入了包的概念。CommonJS 和 AMD 竞争如何最好地定义 JS 模块,而像 Grunt、Gulp 和 Broccoli 这样的构建工具则在竞争如何将这些模块组合成一个可交付的最终产品。在大多数情况下,它们都是类似于任务运行器的工具,它们其实可以构建任何东西,只是碰巧支持构建 JavaScript 而已,当然还包括 HTML、CSS/SASS/LESS 和其他 web 应用需要的内容
需要学到了很多东西,它们都是重要的基础经验,包括:
基于 URL 的路由是基础,没有路由的应用会破坏 Web,而且在框架的设计之初就要考虑到这一点。
通过模板语言扩展 HTML 是一个非常强大的抽象概念。即便它有时看上去很笨拙,但是它能够让用户界面与状态之间的同步变得更加容易。
SPA 的性能是很难解决的问题,web 有很多原生应用所没有的额外限制。我们需要通过网络发送所有的代码,让它 JIT(即时编译)并运行,这样我们的应用才能开始执行,而原生应用则早就已经下载和编译好了。这是一项艰巨的任务。
作为一门语言,JavaScript 有很多问题,它真的需要改进,以便于达成更好的效果,仅靠框架并不能实现这一点。
我们绝对需要更好的构建工具、模块和打包机制,以便编写大规模的应用
三、组件化视图层
React 发明了组件,在.NET 的 XAML 中就有类似的技术,而 web component 也在那时开始作为一项规范发展起来。
扩展 HTML,减少长期存在的状态,将 JS 的业务逻辑直接与模板关联起来(不管具体是使用 JSX、Handlebars 还是 Directives)。基于组件的应用消除了完成任务所需的大部分抽象,并且明显简化了代码的生命周期,也就是一切内容都与组件的生命周期而不是应用的生命周期关联在一起
框架开始把自己宣传成“视图层(view-layer)”,而不是完整的框架,不再试图解决前端应用面临的所有问题,而只是专注于解决渲染问题。如路由、API 通信和状态管理,则由用户自己决定。这个时代著名的框架包括:
1.React.js
2.Vue.js
3.Svelte
4.Polymer.js
应用程序仍然庞大、臃肿、复杂,状态仍然难以管理,路由和 SSR 等基本问题仍然需要解决,。第一代框架是在 ES6 之前诞生的,这要早于模块规范,早于 Babel 和 Webpack。随着这些框架摸索出最佳实践,
JavaScript 生态系统的发展非常迅速,还发生了一些其他的重要变化,
像 Babel 这样的转译器成为常态,并帮助实现了语言的现代化。借助它们,我们不必等待许多年才能使用标准化的特性,而是马上就是使用,语言本身也开始以更快的节奏增加新的特性。
ES 模块被标准化,使我们最终能够开始围绕它们构建现代化的构建工具,如 Rollup、Webpack 和 Parcel。基于 bundling 的导入慢慢成为规范,甚至样式和图片等非 JS 资产也是如此,这极大地简化了构建工具的配置,使它们变得更精简、更快速,而且总体上更好。
随着越来越多的 API 被标准化,Node 和 Web 标准之间的差距也慢慢缩小。SSR 开始逐渐成为可能,然后成为每个严肃的应用都要做的事情,但每次都需要定制化的设置。
边缘计算的出现,使基于 JavaScript 的服务器应用也在分发 / 响应时间方面获得了 SPA 的好处(由于是 CDN 上的静态文件,所以 SPA 一般可以更快地开始加载,即便最后完全加载和渲染可能需要更长时间)。
四、全栈框架
最新的这个框架时代,深入到了 Ember 渲染层的内部,试图清理那些作为第一代框架所具有的上述技术债务,所有的这些第三代框架都是围绕上一代的视图层框架建立的。代表性的框架包括:
1.Next.js(React)
2.Nuxt.js(Vue)
3.Remix(React)
4.SvelteKit(Svelte)
5.Gatsby(React)
6.Astro(Any)
这些框架是随着视图层的成熟和巩固而出现的。既然我们都同意组件是核心原语(core primitive),其他的内容都要基于它来构建,那么标准化应用的其他组成部分,如路由器、构建系统、文件结构等,这些元框架(meta-framework)开始构建与第一代框架类似的开箱即用的一站式解决方案,也就是从各自的生态系统中挑选最佳模式,并随着它们的成熟而将其纳入。
SPA 一直都只关注客户端。SSR 是每个框架都希望解决的问题,但只是作为一种优化,一种进行渲染的方式,最终会在数兆字节的 JS 加载完毕后被取代。只有一个第一代框架敢于想得更远,那就是 Meteor.js,但它的 ”同构(isomorphic)JS“的想法从未得到广泛认可。
将服务器端的 OAuth 添加到我们的应用中,这样 auth token 就不会离开服务器,同时实现一个 API 代理,在向我们的 API 发送请求时添加 token。
将某些路由直接代理到 CDN,这样我们就可以托管在任何其他框架中构建的静态 HTML 页面,允许用户制作自己的自定义页面(我们为一些客户提供的服务)。
当使用需要密匙的外部服务时,添加多个不同的一次性 API 路由(不需要为 API 添加全新的路由并与后端人员协调)。
将对 LaunchDarkly 的使用转移到服务器端,这样我们可以加载更少的 JS,从而降低整体成本。
通过使用后端路由代理 Sentry 请求,我们可以捕捉到由于广告屏蔽器而未被报告的错误。
WebAssembly 可以以一种令人难以置信的方式迭代该模式,任何语言编写一个全栈的框架。同构的 Rust、Python、Swift、Java 等语言最终可以将前台和后台之间的障碍完全消除,只需要在系统中增加一点 HTML 模板