欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

WEB前段開發如何使用流式渲染技術提升用戶體驗

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

什么是流式渲染?

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

流式渲染不是什么新鮮的技術。早在90年代,網頁瀏覽器就已經開始使用這種方式來處理HTML文檔。

在 SPA (單頁應用)流行的時代,由于 SPA 的核心是客戶端動態地渲染內容,流式渲染沒有得到太多關注。如今,隨著服務端渲染相關技術的成熟,流式渲染成為可以顯著提升首屏加載性能的利器。

素材來源于文章

Node.js 實現簡單流式渲染

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 中的一等公民,其設計時考慮到了流式傳輸和低延遲。這使得 Node.js 非常適合作為 Web 庫或框架的基礎。

———— Node.js官網

Node.js 在設計之初就考慮到了流式傳輸數據,考慮如下代碼:

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

// 假設數據需要 5 秒的時間來獲取
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');
});

這是一個簡化的業務場景,運行起來后,會在5秒的白屏后顯示一段 hello world 文字。

沒有用戶會喜歡一個會白屏5秒的網頁!在 web.dev 對 TTFB 的介紹中,加載第一個字節的時間應該在 800ms 內才是良好的 web 網站服務。

我們可以利用流式渲染技術來改善這一點,先通過渲染一個 loading 或者骨架屏之類的東西來改善用戶體驗。查看改進后的代碼:

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

// 假設數據需要 5 秒的時間來獲取
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');
});

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

需要注意的是:Safari 瀏覽器對于何時觸發流式傳輸可能有一些限制(以下內容未找到官方說明,通過實踐總結得到):

  • 傳輸的 chunk 需大于 512 字節

  • 傳輸的內容需能夠在屏幕上實際渲染,例如傳輸 <div style="display:none;">...</div> 可能是不生效的。

聲明式 Shadow DOM,不依賴 javascript 實現

上面的代碼中,我們用到了一些 javascript,本質上我們需要預先渲染一部分 html 標簽作為占位,之后在用新的 html 標簽去替換他們。這用 javascript 很好實現,如果我們禁用了 javascript 呢?

這可能需要一些 Shadow DOM 的技巧!很多組件化設計前端框架都有 slot 的概念,在 Shadow DOM 中也提供了 slot 標簽,可以用于創建可插入的 Web Components。在 chrome 111 版本以上,我們可以使用聲明式 Shadow DOM,不依賴 javascript,在服務器端使用 shadow DOM。一個聲明式 Shadow DOM 的例子:

    <template shadowrootmode="open">
     <header>Header</header>
     <main>
       <slot name="hole"></slot>
     </main>
     <footer>Footer</footer>
   </template>

   <div slot="hole">插入一段文字!</div>

渲染結果如下:

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

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

// 假設數據需要 5 秒的時間來獲取
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');
});

運行這段代碼,和之前的代碼結果完全一致,不同的,當我們禁用掉瀏覽器的 javascript,代碼也一樣正常運行!

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

react 實現流式渲染

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

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>
 )
}

運行這段代碼,和之前的代碼結果完全一致,同樣也不需要運行任何客戶端的 javascript 代碼。

關于 react 的流式渲染在這里能看到官方技術層面上的解釋。本文作為對于流式渲染的概覽,不作更細致的講解。

總結

本文從理論上探討了流式渲染相關實現方案,理論上,流式渲染很簡單。HTTP 標準和 Node.js 很早之前就支持了這一特性。但在工程實踐中,它很復雜。例如對于 react 來說,流式渲染不僅僅需要 react 作為 UI 來支持,也需要借助 nextjs 這種元框架(meta framework)提供服務端的能力。

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

作者: 李章魚


該文章在 2024/12/11 11:24:41 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved