日韩欧美国产精品免费一二-日韩欧美国产精品亚洲二区-日韩欧美国产精品专区-日韩欧美国产另-日韩欧美国产免费看-日韩欧美国产免费看清风阁

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

WEB前段開(kāi)發(fā)如何使用流式渲染技術(shù)提升用戶(hù)體驗(yàn)

admin
2024年12月11日 11:24 本文熱度 817

什么是流式渲染?

流式渲染主要思想是將HTML文檔分塊(chunk)并逐塊發(fā)送到客戶(hù)端,而不是等待整個(gè)頁(yè)面完全生成后再發(fā)送。

流式渲染不是什么新鮮的技術(shù)。早在90年代,網(wǎng)頁(yè)瀏覽器就已經(jīng)開(kāi)始使用這種方式來(lái)處理HTML文檔。

在 SPA (單頁(yè)應(yīng)用)流行的時(shí)代,由于 SPA 的核心是客戶(hù)端動(dòng)態(tài)地渲染內(nèi)容,流式渲染沒(méi)有得到太多關(guān)注。如今,隨著服務(wù)端渲染相關(guān)技術(shù)的成熟,流式渲染成為可以顯著提升首屏加載性能的利器。

素材來(lái)源于文章

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

HTTP is a first-class citizen in Node.js, designed with streaming and low latency in mind. This makes Node.js well suited for the foundation of a web library or framework.

HTTP 是 Node.js 中的一等公民,其設(shè)計(jì)時(shí)考慮到了流式傳輸和低延遲。這使得 Node.js 非常適合作為 Web 庫(kù)或框架的基礎(chǔ)。

———— Node.js官網(wǎng)

Node.js 在設(shè)計(jì)之初就考慮到了流式傳輸數(shù)據(jù),考慮如下代碼:

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

// 假設(shè)數(shù)據(jù)需要 5 秒的時(shí)間來(lái)獲取
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è)簡(jiǎn)化的業(yè)務(wù)場(chǎng)景,運(yùn)行起來(lái)后,會(huì)在5秒的白屏后顯示一段 hello world 文字。

沒(méi)有用戶(hù)會(huì)喜歡一個(gè)會(huì)白屏5秒的網(wǎng)頁(yè)!在 web.dev 對(duì) TTFB 的介紹中,加載第一個(gè)字節(jié)的時(shí)間應(yīng)該在 800ms 內(nèi)才是良好的 web 網(wǎng)站服務(wù)。

我們可以利用流式渲染技術(shù)來(lái)改善這一點(diǎn),先通過(guò)渲染一個(gè) loading 或者骨架屏之類(lèi)的東西來(lái)改善用戶(hù)體驗(yàn)。查看改進(jìn)后的代碼:

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

// 假設(shè)數(shù)據(jù)需要 5 秒的時(shí)間來(lái)獲取
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');
});

使用流式渲染后,這個(gè)頁(yè)面最初顯示 "loading...",然后在 5 秒后更新為 "Hello World"。

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

  • 傳輸?shù)?chunk 需大于 512 字節(jié)

  • 傳輸?shù)膬?nèi)容需能夠在屏幕上實(shí)際渲染,例如傳輸 <div style="display:none;">...</div> 可能是不生效的。

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

上面的代碼中,我們用到了一些 javascript,本質(zhì)上我們需要預(yù)先渲染一部分 html 標(biāo)簽作為占位,之后在用新的 html 標(biāo)簽去替換他們。這用 javascript 很好實(shí)現(xiàn),如果我們禁用了 javascript 呢?

這可能需要一些 Shadow DOM 的技巧!很多組件化設(shè)計(jì)前端框架都有 slot 的概念,在 Shadow DOM 中也提供了 slot 標(biāo)簽,可以用于創(chuàng)建可插入的 Web Components。在 chrome 111 版本以上,我們可以使用聲明式 Shadow DOM,不依賴(lài) javascript,在服務(wù)器端使用 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>

渲染結(jié)果如下:

可以看到,我們的文字被插入在了 slot 標(biāo)簽中,利用聲明式 Shadow DOM,我們可以改寫(xiě)上面的例子:

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

// 假設(shè)數(shù)據(jù)需要 5 秒的時(shí)間來(lái)獲取
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é)果完全一致,不同的,當(dāng)我們禁用掉瀏覽器的 javascript,代碼也一樣正常運(yùn)行!

聲明式 Shadow DOM 是一個(gè)比較新的特性,可以在這篇文檔中看到更多內(nèi)容。

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

我們換個(gè)視角看看 react,react 18 之后在框架層面上支持了流式渲染, 下面是使用 nextjs 改寫(xiě)上面的代碼:

import { Suspense } from 'react'


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)行這段代碼,和之前的代碼結(jié)果完全一致,同樣也不需要運(yùn)行任何客戶(hù)端的 javascript 代碼。

關(guān)于 react 的流式渲染在這里能看到官方技術(shù)層面上的解釋。本文作為對(duì)于流式渲染的概覽,不作更細(xì)致的講解。

總結(jié)

本文從理論上探討了流式渲染相關(guān)實(shí)現(xiàn)方案,理論上,流式渲染很簡(jiǎn)單。HTTP 標(biāo)準(zhǔn)和 Node.js 很早之前就支持了這一特性。但在工程實(shí)踐中,它很復(fù)雜。例如對(duì)于 react 來(lái)說(shuō),流式渲染不僅僅需要 react 作為 UI 來(lái)支持,也需要借助 nextjs 這種元框架(meta framework)提供服務(wù)端的能力。

原文鏈接:https://juejin.cn/post/7347009547741495350

作者: 李章魚(yú)


該文章在 2024/12/11 11:24:41 編輯過(guò)
關(guān)鍵字查詢(xún)
相關(guān)文章
正在查詢(xún)...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專(zhuān)業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車(chē)隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類(lèi)企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷(xiāo)售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶(hù)的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 无人区一码二码三码四码区 | 亚洲欧美一区二区三区国产 | 国产午夜不卡 | 在线看片国产日韩欧美亚洲 | 97国产| 午夜视频在线播放 | 观看日本电影 | 国产午夜高清高清在线观看 | 亚洲国产砖一线二线 | 日韩制服丝 | 国产盗摄亚洲中国 | 91国产最 | 亚洲国产精品国语在线 | 国人精品视频在线观看 | 日亚洲第 | 亚洲国产精品一区二区九九 | 天天咱天咱天干天谢 | 麻花传媒免费网站在线观看 | 国产福利| 另类专区国产在 | 2025最新电| 永久精品电影在线观看 | 国产区一二三四区2025 | 精品国产女主播在线观看 | 欧美一级在线观看 | 亚洲综合一区三区 | 欧美亚洲综合成人a∨在线 亚洲国产中文字幕在线观看 | 日韩一区 | 三级精品在线观看自拍 | 国产精品宾馆精品酒店 | 香港日本韩国三级网站 | 日本一区二区三区不卡视频中 | 日韩一区精品在线观看 | 在线观看国产一线天木耳奈奈 | 91色色| 综合国产| 国产日产欧产美韩 | 国产a级三级三区成人国产一级婬 | 激情欧美日韩一区二区 | 日本高清乱理伦片中文字幕 | 青青青爽国产 |