一緒に書く習慣をつけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して3日目です。クリックしてイベントの詳細をご覧ください。
I.概要
フロントエンドテクノロジースタックとツールチェーンの成熟が繰り返されるにつれて、フロントエンドエンジニアリングとモジュール化が主流のテクノロジーソリューションになりました。React、Vue、Angularなどのフロントエンドテクノロジーのこの波の中で、フロントエンドフレームワーク、そのようなフレームワークによって構築された単一ページアプリケーション(SPA)には、優れたユーザーエクスペリエンス、優れたレンダリングパフォーマンス、および高い保守性という利点があります。しかし、いくつかの大きな欠陥もあり、主に次の2つの点が関係しています。
- 折り目の上の読み込みに時間がかかりすぎる
サーバーによってレンダリングされたHTMLを直接取得する従来のサーバー側レンダリングとは異なり、シングルページアプリケーションはJavaScriptを使用してクライアント側でHTMLを生成し、コンテンツをレンダリングします。ユーザーはクライアント側のJS解析を待つ必要があります。ページが表示される前に実行が完了するため、最初の画面の読み込み時間が長くなり、ユーザーエクスペリエンスに影響します。
- SEOに悪い
検索エンジンがWebサイトのHTMLファイルをクロールする場合、Webページコンテンツを生成するにはクライアント側のJavaScriptで解析および実行する必要があるため、シングルページアプリケーションのHTMLにはコンテンツがありません。現在の主流の検索エンジンは次のとおりです。コンテンツのこの部分をクロールするのはあまり得意ではありません。
これらの2つの欠陥を解決するために、業界は従来のサーバー側のストレートHTMLソリューションを利用し、サーバー側でフロントエンドフレームワーク(React / Vue / Angular)コードを実行してWebページコンテンツを生成することを提案しています。次に、レンダリングされたWebページのコンテンツをクライアントに返します。クライアントは表示のみを担当する必要があります。
もちろん、それだけでなく、より良いユーザーエクスペリエンスを得るために、サーバーからレンダリングされたコンテンツはSPAアプリケーションとしてクライアント側でアクティブ化されます。つまり、後続のページコンテンツの相互作用はクライアント側で処理されます。レンダリング。
一言で言えばこのように:
- 最初の画面をサーバー側で直接レンダリングすることで、最初の画面のレンダリングが遅くなり、SEOが悪化するという問題を解決します。
- より良いユーザーエクスペリエンスのために、クライアント側のレンダリングを通じてページコンテンツの相互作用を引き継ぎます
这种方式我们通常称之为现代化的服务端渲染,也叫同构渲染,所谓的同构指的就是服务端构建渲染 + 客户端构建渲染。同理,这种方式构建的应用称之为服务端渲染应用或者是同构应用。
为了让大家更好的理解服务端渲染应用以及我们为什么需要现代化的服务端渲染,我将从以下三个方面来讲解:
- 传统的服务端渲染
- 客户端渲染
- 现代化的服务端渲染(同构渲染)
二、传统的服务端渲染
早期Web页面渲染都是在服务端完成的,即服务端运行过程中将所需的数据结合页面模板渲染为HTML,响应给客户端浏览器,所以浏览器呈现出来的是直接包含内容的页面。相信接触过JSP的同学应该对它的工作流程不陌生吧:
我本科学校开设的课程学过一点JSP这个技术,但是这是一篇针对前端同学的文章,无论如何这种方式对于没有玩儿过后端开发的同学来说可能会比较陌生,所以下面通过我们前端同学比较熟悉的 Node.js 来了解一下这种方式。
创建工作目录:
mkdir preSSR-demo
cd preSSR-demo
复制代码
安装依赖:
# 创建 http 服务
npm i express
# 服务端模板引擎
npm i art-template express-art-template
复制代码
服务端代码:
- 基本的 Web 服务
- 使用模板引擎
- 渲染一个页面
server.js
const express = require('express')
const fs = require('fs')
const template = require('art-template')
const app = express()
app.get('/', (req, res) => {
// 1. 得到模板内容
const templateStr = fs.readFileSync('./index.html', 'utf-8')
// 2. 得到数据
const data = JSON.parse(fs.readFileSync('./data.json', 'utf-8'))
// 3. 渲染:数据 + 模板 = 完整结果
const html = template.render(templateStr, data)
// 4. 把渲染结果发送给客户端
res.send(html)
})
app.listen(3000, () => console.log('running...'))
复制代码
客户端代码:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>传统的服务端渲染</title>
</head>
<body>
<h1>传统的服务端渲染</h1>
<h2>{{ title }}</h2>
<ul>
{{ each posts }}
<li>{{ $value.title }}</li>
{{ /each }}
</ul>
</body>
</html>
复制代码
这也就是最早的网页渲染方式,也就是动态网站的核心工作步骤。在这样的一个工作过程中,因为页面 中的内容不是固定的,它有一些动态的内容。
在今天看来,这种渲染模式是不合理或者说不先进的。因为在当下这种网页越来越复杂的情况下,这种模式存在很多明显的不足:
- 应用的前后端部分完全耦合在一起,在前后端协同开发方面会有非常大的阻力;
- 前端没有足够的发挥空间,无法充分利用现在前端生态下的一些更优秀的方案;
- 由于内容都是在服务端动态生成的,所以服务端的压力较大;
- 相比目前流行的 SPA 应用来说,用户体验一般;
但是不得不说,在网页应用并不复杂的情况下,这种方式也是可取的。
三、客户端渲染
传统的服务端渲染有很多问题,但是这些问题随着客户端 Ajax 技术的普及得到了有效的解决,Ajax 技术可以使得客户端动态获取数据变为可能,也就是说原本服务端渲染这件事儿也可以拿到客户端做了。下面是基于客户端渲染的 SPA 应用的基本工作流程:
我们平时使用Vue.js开发单页面应用就是这个流程,这里就不再演示。这种模式下,我们就可以把【数据处理】和【页码渲染】这两件事儿分开了,也就是【后 端】负责数据处理,【前端】负责页面渲染,这种分离模式极大的提高了开发效率和可维护性。
但是这种模式下,也会存在一些明显的不足,其中最主要的就是:
- 首屏渲染慢:因为 HTML 中没有内容,必须等到 JavaScript 加载并执行完成才能呈现页面内容。
- SEO 问题:同样因为 HTML 中没有内容,所以对于目前的搜索引擎爬虫来说,页面中没有任何有用的信息,自然无法提取关键词,进行索引了。
对于客户端渲染的 SPA 应用的问题有没有解决方案呢?答案是:有
服务端渲染,严格来说是现代化的服务端渲染,也叫同构渲染
四、现代化的服务端渲染(前端进阶必备)
我们在上一小节了解到 SPA 应用有两个非常明显的问题:
- 首屏加载慢
- 不利于SEO
我们只是把问题抛出来了,那有没有解决办法呢? 答案就是:服务端渲染。 也就是将客户端渲染的工作放到服务端渲染,这个问题不就解决了吗? 但是有的同学肯定会想要问,是再让我们回到传统的服务端渲染吗?
不不不,本质上确实是需要使用到传统的服务端渲染,但是严格来讲应该叫现代化的服务端渲染,也叫同构渲染,也就是【服务端渲染】 + 【客户端渲染】。可能听起来有点晕,这个概念我们待会儿就会了解到。
Nuxt.js 是一个基于 Vue.js 生态开发的一个第三方服务端渲染框架,通过它我们可以轻松构建现代化的 服务端渲染应用。 isomorphic web apps(同构应用):isomorphic/universal,基于 react、vue 框架,客户端渲染和 服务器端渲染的结合,在服务器端执行一次,用于实现服务器端渲染(首屏直出),在客户端再执行一 次,用于接管页面交互,核心解决 SEO 和首屏渲染慢的问题。
- 客户端发起请求
- 服务端渲染首屏内容 + 生成客户端 SPA 相关资源
- 服务端将生成的首屏资源发送给客户端
- 客户端直接展示服务端渲染好的首屏内容
- 首屏中的 SPA 相关资源执行之后会激活客户端 Vue
- 之后客户端所有的交互都由客户端 SPA 处理
我们来分析一下同构渲染的优缺点:
- 优点:首屏渲染速度快、有利于 SEO
- 缺点:
- 开发成本高。
- 涉及构建设置和部署的更多要求。与可以部署在任何静态文件服务器上的完全静态单页面应用程序 (SPA) 不同,服务器渲染应用程序,需要处于 Node.js server 运行环境。
- 更多的服务器端负载。在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用 CPU 资源 (CPU-intensive - CPU 密集),因此如果你预料在高流量环境 (high traffic) 下使用,请准备相应的服务器负载,并明智地采用缓存策略。
相关技术
- React 生态中的 Next.js
- Vue 生态中的 Nuxt.js
- Angular 生态中的 Angular Universal
五、该不该使用服务端渲染
アプリケーションでサーバーサイドレンダリング(SSR)を使用する前に最初に尋ねる必要があるのは、それが本当に必要かどうかです。これは、コンテンツ作成までの時間がアプリケーションにとってどれほど重要であるかに大きく依存します。たとえば、内部ダッシュボードを構築している場合、初期ロードでの余分な数百ミリ秒は問題ではありません。その場合、サーバー側レンダリング(SSR)を使用するのは簡単です。ただし、コンテンツまでの時間の要件は絶対に重要な指標です。この場合、サーバー側のレンダリング(SSR)は、最高の初期ロードパフォーマンスを達成するのに役立ちます。
実際、多くのWebサイトでは、効率上の理由からサーバー側のレンダリングが有効になっており、パフォーマンスは2番目です。ウェブサイトAのページに「フロントエンドパフォーマンス最適化」というキーワードがあるとします。このキーワードは、JSコードが実行された後にHTMLページに追加されます。次に、クライアント側のレンダリングモードでは、検索エンジンでこのキーワードを検索してもWebサイトAが見つかりません。検索エンジンは既製のコンテンツのみを検索し、JSコードは実行しません。ウェブサイトAの運営者がこの状況を見たとき、彼は非常に大きな気持ちになりました。検索エンジンはそれを見つけることができず、ユーザーは私たちを見つけることができませんでした。「既製のコンテンツ」を検索エンジンに表示するには、サイトAでサーバー側のレンダリングを有効にする必要がありました。しかし、パフォーマンスは2番目であり、パフォーマンスが重要ではないという意味ではありません。