成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

我們一起聊聊如何通過流式渲染提升用戶體驗(yàn)?

開發(fā) 前端
本文從理論層面深入探討了流式渲染的相關(guān)實(shí)現(xiàn)方案。理論上,流式渲染的概念和實(shí)現(xiàn)相對(duì)簡單。HTTP 標(biāo)準(zhǔn)和 Node.js 早在很久以前就對(duì)這一特性提供了支持。

什么是流式渲染?

流式渲染的核心理念是將 HTML 文檔分割成小塊(chunk),并逐步地發(fā)送給客戶端,而非等待整個(gè)頁面完整生成后再進(jìn)行傳輸。這種方式能夠極大地提升用戶的初始加載體驗(yàn),特別是在網(wǎng)絡(luò)條件不佳或者頁面內(nèi)容復(fù)雜的情況下。

流式渲染并非新興技術(shù),早在 90 年代,網(wǎng)頁瀏覽器就已開始運(yùn)用這種模式來處理 HTML 文檔。不過,在 SPA(單頁應(yīng)用)大行其道的時(shí)期,由于其核心在于客戶端動(dòng)態(tài)渲染內(nèi)容,流式渲染未能引起廣泛關(guān)注。然而,現(xiàn)今隨著服務(wù)端渲染技術(shù)的日臻成熟,流式渲染已成為顯著優(yōu)化首屏加載性能的有力手段。

Node.js 實(shí)現(xiàn)簡單流式渲染

HTTP 是 Node.js 中的一等公民,其在設(shè)計(jì)時(shí)就充分考慮了流式傳輸和低延遲特性。這使得 Node.js 極為適合作為 Web 庫或框架的構(gòu)建基礎(chǔ)。 ———— Node.js 官網(wǎng)

Node.js 從設(shè)計(jì)之初就將流式傳輸數(shù)據(jù)納入考量,以下是一個(gè)簡單的示例代碼:

const Koa = require('koa');
const app = new Koa();

// 假設(shè)數(shù)據(jù)需要 5 秒的時(shí)間來獲取
renderAsyncString = async () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('<h1>Hello World</h1>');
    }, 5000);
  })
}

app.use(async (ctx, next) => {
  ctx.type = 'html';
  ctx.body = await renderAsyncString();
  await next();
});

app.listen(3000, () => {
  console.log('App is listening on port 3000');
});

這是一個(gè)簡化的業(yè)務(wù)場景,運(yùn)行之后,會(huì)出現(xiàn)長達(dá) 5 秒的白屏,然后才顯示出"Hello World"這段文字。

毫無疑問,沒有用戶會(huì)愿意忍受一個(gè)長達(dá) 5 秒的白屏網(wǎng)頁!在 web.dev[1] 對(duì)于 TTFB(Time To First Byte,首字節(jié)時(shí)間)的介紹中提到,加載第一個(gè)字節(jié)的時(shí)間應(yīng)當(dāng)控制在 800ms 以內(nèi),才能稱得上是優(yōu)質(zhì)的 Web 網(wǎng)站服務(wù)。

為了改善這種情況,我們可以借助流式渲染技術(shù)。比如,先向用戶呈現(xiàn)一個(gè)加載中的提示或者骨架屏,以此來優(yōu)化用戶體驗(yàn)。下面是改進(jìn)后的代碼:

const Koa = require('koa');
const app = new Koa();
const Stream = require('stream');

// 假設(shè)數(shù)據(jù)需要 5 秒的時(shí)間來獲取
renderAsyncString = async () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('<h1>Hello World</h1>');
    }, 5000);
  })
}

app.use(async (ctx, next) => {
  const rs = new Stream.Readable();
  rs._read = () => {};
  ctx.type = 'html';
  rs.push('<h1>loading...</h1>');
  ctx.body = rs;
  renderAsyncString().then((string) => {
    rs.push(`<script>
      document.querySelector('h1').innerHTML = '${string}';
    </script>`);
  })
});

app.listen(3000, () => {
  console.log('App is listening on port 3000');
});

采用流式渲染后,頁面最初會(huì)顯示"loading...",然后在 5 秒后更新為"Hello World"。

需要特別注意的是,Safari 瀏覽器對(duì)于何時(shí)觸發(fā)流式傳輸可能存在一些限制(以下內(nèi)容未找到官方說明,而是通過實(shí)踐總結(jié)得出):

  • 傳輸?shù)?chunk 大小需大于 512 字節(jié)。若小于此值,可能無法有效觸發(fā)流式傳輸,影響用戶體驗(yàn)。
  • 傳輸?shù)膬?nèi)容必須能夠在屏幕上實(shí)際渲染。例如,傳輸<div style="display:none;">...</div>這樣隱藏的內(nèi)容可能是無效的,無法實(shí)現(xiàn)流式渲染的預(yù)期效果。

聲明式 Shadow DOM,不依賴 javascript 實(shí)現(xiàn)

在上述的代碼中,我們運(yùn)用了一定的 JavaScript 代碼。本質(zhì)上,我們需要預(yù)先渲染一部分 HTML 標(biāo)簽作為占位,隨后再用新的 HTML 標(biāo)簽對(duì)其進(jìn)行替換。使用 JavaScript 來實(shí)現(xiàn)這一過程相對(duì)容易,但如果禁用了 JavaScript 呢?

這就可能需要借助一些 Shadow DOM[2] 的技巧!眾多組件化設(shè)計(jì)的前端框架都包含了 slot(插槽)的概念,在 Shadow DOM 中也提供了 slot 標(biāo)簽,其可用于創(chuàng)建可插入的 Web Components。在 Chrome 111 及以上版本中,我們能夠使用聲明式 Shadow DOM,無需依賴 JavaScript,在服務(wù)器端就能實(shí)現(xiàn) shadow DOM 的功能。以下是一個(gè)聲明式 Shadow DOM 的示例:

<template shadowrootmode="open">
      <header>Header</header>
      <main>
        <slot name="hole"></slot>
      </main>
      <footer>Footer</footer>
    </template>
  
    <div slot="hole">插入一段文字!</div>

從中可以清晰地看到,我們的文字成功插入到了 slot 標(biāo)簽之中。利用聲明式 Shadow DOM,我們能夠?qū)χ暗氖纠M(jìn)行改寫:

const Koa = require('koa');
const app = new Koa();
const Stream = require('stream');

// 假設(shè)數(shù)據(jù)需要 5 秒的時(shí)間來獲取
renderAsyncString = async () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('<h1>Hello World</h1>');
    }, 5000);
  })
}

app.use(async (ctx, next) => {
  const rs = new Stream.Readable();
  rs._read = () => {};
  ctx.type = 'html';
  rs.push(`
  <template shadowrootmode="open">
    <slot name="hole"><h1>loading</h1></slot>
  </template>
  `);
  ctx.body = rs;
  renderAsyncString().then((string) => {
    rs.push(`<h1 slot="hole">${string}</h1>`);
    rs.push(null);
  })
});

app.listen(3000, () => {
  console.log('App is listening on port 3000');
});

運(yùn)行這段改寫后的代碼,其結(jié)果與之前完全相同。更為重要的是,即便我們禁用了瀏覽器的 JavaScript,代碼依然能夠正常運(yùn)行!

聲明式 Shadow DOM 是一個(gè)相對(duì)較新的特性,您可以在這篇文檔[3]中獲取更多詳細(xì)信息。

react 實(shí)現(xiàn)流式渲染

現(xiàn)在讓我們轉(zhuǎn)換視角,來看看 React 框架中的流式渲染。自 React 18 版本之后,在框架層面上開始支持流式渲染。下面是使用 nextjs 對(duì)之前的示例進(jìn)行改寫的代碼:

import { Suspense } from 'eact'

const renderAsyncString = async () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Hello World!');
    }, 5000);
  })
}

async function Main() {
  const string = await renderAsyncString();
  return <h1>{string}</h1>
}

export default async function App() {
  return (
    <Suspense fallback={<h1>loading...</h1>} >
      <Main />
    </Suspense>
  )
}

運(yùn)行這段代碼,其效果與之前的示例完全一致,并且同樣無需運(yùn)行任何客戶端的 JavaScript 代碼。

關(guān)于 React 的流式渲染,您可以在官方的技術(shù)層面[4]解釋中獲取更深入的信息。在本文中,僅作為對(duì)流式渲染的概要介紹,不對(duì)其進(jìn)行更為細(xì)致的講解。

總結(jié)

本文從理論層面深入探討了流式渲染的相關(guān)實(shí)現(xiàn)方案。理論上,流式渲染的概念和實(shí)現(xiàn)相對(duì)簡單。HTTP 標(biāo)準(zhǔn)和 Node.js 早在很久以前就對(duì)這一特性提供了支持。然而,在實(shí)際的工程應(yīng)用中,流式渲染并非易事。以 React 為例,要實(shí)現(xiàn)流式渲染,不僅需要 React 自身作為用戶界面(UI)框架提供支持,還需要借助像 nextjs 這樣的元框架(meta framework)來賦予服務(wù)端相應(yīng)的能力。

責(zé)任編輯:武曉燕 來源: 量子前端
相關(guān)推薦

2024-01-29 09:01:20

React列表模式

2024-08-05 08:24:06

java外網(wǎng)Nginx

2023-08-10 08:28:46

網(wǎng)絡(luò)編程通信

2023-08-04 08:20:56

DockerfileDocker工具

2023-06-30 08:18:51

敏捷開發(fā)模式

2023-09-10 21:42:31

2022-05-24 08:21:16

數(shù)據(jù)安全API

2024-11-27 16:07:45

2024-09-30 09:33:31

2021-08-27 07:06:10

IOJava抽象

2024-02-20 21:34:16

循環(huán)GolangGo

2024-09-09 00:00:00

編寫技術(shù)文檔

2023-04-03 00:09:13

2024-12-10 00:00:25

2021-12-10 07:45:48

字節(jié)音頻視頻

2022-08-30 13:48:16

LinuxMySQL內(nèi)存

2024-11-27 08:47:12

2021-11-04 06:58:31

CSS性能設(shè)備

2023-11-06 07:21:02

DBaaSApachealpha版本

2022-02-23 08:41:58

NATIPv4IPv6
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美9999 | 日韩视频在线免费观看 | 狠狠伊人| 四虎影院在线观看免费视频 | 男女免费视频网站 | 国产精品福利在线 | 91免费在线 | 91精品国产综合久久久久久 | 久久久久久国模大尺度人体 | 久久久这里都是精品 | 在线观看特色大片免费网站 | 成人综合久久 | 天堂av免费观看 | h视频亚洲| 一区二区在线 | 日韩中文一区二区三区 | 亚洲精品一二三区 | 亚洲精品一区二区三区四区高清 | 久久爱一区 | 亚洲综合色 | 久久蜜桃av一区二区天堂 | 99精品99 | 秋霞国产 | 婷婷久久五月 | 亚洲精品视频在线看 | 国产乱码精品一区二区三区中文 | 午夜爱爱毛片xxxx视频免费看 | 天天天天天操 | 国产第一区二区 | 老司机精品福利视频 | 中文字幕一区在线观看视频 | 亚洲社区在线 | 亚洲精品国产第一综合99久久 | 午夜视频在线 | 亚洲午夜精品视频 | 欧美激情精品久久久久久 | 不卡在线视频 | 一级片毛片 | 成人av一区| 久久久久久亚洲 | 精品国产一区二区三区性色 |