• 欢迎使用千万蜘蛛池,网站外链优化,蜘蛛池引蜘蛛快速提高网站收录,收藏快捷键 CTRL + D

盐城seo优化用户体验(盐城优化公司咨询23火星)


开篇

前端同构渲染的相关架构,给我最直观的感受,这是前端渲染最为复杂的一种方案,也是为了追求极致的用户体验不得不去做的一种尝试,虽然 Node.js 的引入赋能了传统前端领域、SEO 优化也不再是个问题,但很明显,这些只是副产品。

问题

上帝为了我们开了一扇窗,同时也会为我们关上一扇门。

我们所知的传统型 SPA,单页面应用,贴近用户端越近,交互越复杂,它的弊端就越明显,在我们享受 JavaScirpt 给我们带来的无刷新体验和组件化带来的开发效率的同时,『白屏』这个随着 SPA 各种优点随之而来的缺点被遗忘,我们拥有菊花方案在 JavaScript 没有将 DOM 构建好之前蒙层,拥有白屏监控方案将真实用户数据上报改进,但并没有触碰到白屏问题的本质,那就是『DOM 的构建者是 JavaScript,而非原生的浏览器』。


如上代码,在 SPA 架构中,服务器端直接给出形如这样的 HTML,浏览器在渲染 body#root 这个节点完成之后,页面的绘制区域其实还是空的,直到 render.js 构建好真实的 DOM 结构之后再 append 到 #root上去。此时,首屏展示出来时,必然是 render.js 通过网络请求完毕,然后加上 JavaScript 执行完成之后的。

让我们回到最初的那个前端时代,那时候 JavaScript 还没有那么强大,我们的服务器端全部吐出 HTML 给前端,我们使用 jQuery 解决用户的交互,这种方式虽有很多弊病,但不可否认的是拥有理论上最低白屏时间。


如上代码,在直出的服务器渲染中,浏览器直接拿到最终的 HTML,浏览器通过解析 HTML 之后将 DOM 元素生成而进行渲染。所以相比于 SPA,服务器端渲染从直观上看:

解决

Node.js 的出现极大程度的给传统前端赋予了更大的能量,前端的分离也从前期的物理文件的区分转变为职责上的区分,前端开发者从页面仔的噩梦中解脱出来,最重要的是,JavaScript 能在服务器端执行了。在享受这些红利的同时,我们就会不自觉的设想一种方案,它拥有 SPA 的大部分优点,却解决了它大部分的缺点,那就是服务器端输出 HTML,然后由客户端复用该 HTML,继续 SPA 模式,这样岂不是既解决了白屏和 SEO 问题,又继承了无刷新的用户体验和开发的组件化嘛。

嗯,如果这样的话,就会有个一致性的问题。我们必须在浏览器端复用服务器端输出的 HTML 才能避免多套代码的适配,而传统的模板渲染是可行的,只要选择一套同时支持浏览器和 Node.js 的模板引擎就能搞定。我们写好模板, 在 Node.js 准备好数据,然后将数据灌入模板产出 HTML,输出到浏览器之后由客户端 JavaScript 承载交互,搞定。

软件开发中遇到的所有问题,都可以通过增加一层抽象而得以解决

思路到了这里,我们就会发现,『模板』其实是一种抽象层,虽然底层的 HTML 只能跑在浏览器端,但是顶层的模板却能通过模板引擎同时跑在浏览器和服务器端,此为垂直方向,在水平方向上,模板将数据和结构解耦,将数据灌入结构,这种灌入,实际是一锤子买卖,管生不管养。

随着时间的推进,组件化的大潮来了,其核心概念 Virtual DOM 依其声明式和高性能让前端开发者大呼爽爽爽,但究其本质,就是为了解决频繁操作 DOM 而在 HTML 之上做的一层抽象,与模板不同的是,它将数据与结构产生交互,有代表的要数 Facebook 方使用的单项数据流和 Vue 方使用的 MVVM 数据流,大道至简,我们观察函数 UI = F(data), 其中 UI 为最终产出前端界面,data 为数据,F 则为模板结构或者 Virtual DOM,模板的方式是 F 只执行一遍,而组件方式则为每次 data 改变都会再执行一遍。

所以理论上,无论是模板方式还是组件方式,前后端同构的方案都呼之欲出,我们在 Node.js 端获取数据 ,执行 F 函数,得到 HTML输出给浏览器,浏览器 JavaScript 复用 HTML,继续执行 F 函数,等到数据变化,继续执行 F 函数,交互也得到解决,完美~~~

实施

但由于组件化大势所趋,下文将略去模板方案,我们以 Vue 为类比,下图表明其实施思路:

通用代码

由于 F 同时需要在浏览器端和服务器端执行,所以对于整个 Vue App,我们需要同时支持两端,也就是通用代码。所以我们需要将 SPA 架构的代码进行改造:

构建与运行

新世界

至此,白屏问题问题看起来是解决了,通过把 JavaScript 的渲染逻辑放到 Node.js 端进行,我们加快了首屏出现的时间,但是联想到 Node.js 对前端的赋能,我们或许可以做的更多。

再议首屏

让我们把视角移动的更细致一些,关注『从服务器端输出 HTML』这一部分,其隐藏的含义是我们需要把 App 渲染的所有 HTML 都输出给前端,其实不然,举个栗子:

比如在移动端有一个页面,它有大约 10 屏的高度,如果我们在服务器端全部输出 10 屏其实是有点浪费的,我们可以只输出首屏需要的,从而降低 render 执行时间从而降低 TTFB 时间,让页面更快的到达用户眼前。实践中,一般情况是输出大概快两屏的样子,就能处理所以机型的高度问题,剩下的 8 屏,在浏览器端继续渲染,渐进产出内容,用户无感知。

资源控制

得益于 Node.js 输出 HTML 的另一层含义,就是我们可以直接在首次接触就能感知到客户端,也就有了足够的灵活性,再举个栗子:

有个针对安卓平台和 iOS 平台不同的脚本只要加载,如果在 SPA 情况下,只有等 JavaScript 执行时我们判定 navigation.userAgent 来获知先在是哪个平台,然后在 appendChild 一个 script 到 body,但如果服务端能首次接触就能感知,我们可以在服务端直接拿到 HTTP 请求中的 userAgent 判定平台,根据标识在模板中处理,很显然,这样很稳。

另外,如果有一些特别复杂的计算,服务端可以有更多的办法将数据更快的处理,以避免繁忙无比的浏览器接手。

缓存控制

一般的业务场景下,我们需要在 Node.js 中通过内网将数据获取到,然后通过 render 函数渲染出 HTML(一般需要将数据附带给 HTML 输出以便重复利用),这个时候我们可以通过页面访问地址和生成的 HTML 字符串做缓存策略,在缓存(一般选择 redis 等方案)之后,下次直接将同样的页面直接输出到前端,可大幅提高渲染性能。

但这种方案也有很多限制,因为要考虑页面地址、多平台下、账户是否登录,页面是否需要改动等情况:

挑战

同构渲染看似美好,但其相对传统 SPA 确有着更多挑战:

Node.js

服务器端渲染相对应传统的 Node.js 应用,renderToString 函数不仅 CPU 密集,而且不同的组件对机器资源的要求不尽相同,这就更需要 Node.js 指标的监控、日志的记录、错误的收集、崩溃机制的完善。这里额外的关键的指标是 renderToString 的时间,它反应了 Node.js 渲染所使用的时间,如果加入缓存机制,就需要统计命中率等等。

代码质量

关于写通用代码,要求比 SPA 架构对开发者提出了更高的要求,我们需要小心再小心,因为万一搞错,将导致很难排查的内存泄露和 CPU 飙升,并且一旦出了问题,就像要修理天上跑的飞机一样,非常困难。还记得有一次在类似 componentWillMount 写了一些跟浏览器相关的代码导致的内存飙升,还有一次 JSON.stringify 一个大对象导致的 CPU 飙升,不堪回首。这方面 alinode 做的很好,确实可以满足这种飞机场景。

结语

为了效率, 前端们付出了艰辛的努力,无论是工程上我们千方百计的制造工具,还是组件化的引入,我们解决的是开发的效率,而无论是 Virtual DOM 的引入解决频繁操作的 DOM,还是用了提升用户体验而使用的 SPA 架构,我们解决的是用户的使用效率,是前端的性能。而同构渲染也是这样一种方案,它引入了 Node.js 的复杂度,要求我们写出限制更多的代码,其根本目的还是为了让用户更快更早的看到页面,那怕是 50 毫秒,那怕是 10 毫秒。

本文链接:https://www.24zzc.com/news/169767987148644.html

相关文章推荐

    无相关信息