[譯] 樣式元件 v3.1.0:大幅效能提升並支援服務端流式渲染

Fate_輕舞飛揚發表於2018-02-11

v3.1.0:大幅效能提升並支援服務端流式渲染

在生產環境,一種新的 CSS 注入機制意味著更快的客戶端渲染。 ? 服務端流式渲染可以加快首屏渲染時間! ??

在生產環境更快的 CSS 注入

這個補丁出來很久了,並有很長的歷史。差不多一年半前 Sunil Pai 發現一個新的,卻廣泛未知的 DOM API: insertRule。它允許人們以驚人的速度將 CSS 從 JavaScript 插入到 DOM 中;唯一的缺點就是樣式不能使用瀏覽器開發者工具進行編輯。

GlenMax 首次構建樣式化元件時,他們重點 關注的是開發人員的體驗。效能問題對於較小的應用來說是很稀少的,所以他們決定並不使用 insertRule。隨著採用量不斷增加,人們在更大的應用程式中使用樣式元件,在變化頻率較高的元件中樣式注入成為了效能瓶頸。

感謝 Reddit 的一名前端工程師 Ryan Schwers,樣式元件 v3.1.0 現在預設在生產環境使用 insertRule

[譯] 樣式元件 v3.1.0:大幅效能提升並支援服務端流式渲染

我們將前一個版本 (v3.0.2) 和使用了 insertRule 的新版本的進行了一些對比測試,結果甚至比我們的預期(已經很高的期望)還要高:

測試應用程式的初始掛載時間較之前減少了約 10 倍,重渲染的時間減少了約 20 倍!

請注意,測試結果是壓力測試的結果,並不代表真實的應用程式。雖然你的應用程式掛載時間(可能)不會減少 10 倍,但在我們的一個生產環境下的應用程式中,首次互動時間會下降數百毫秒

在這些基準測試中,樣式元件與其他主流的 React CSS-in-JS 框架相比,效果如何:

[譯] 樣式元件 v3.1.0:大幅效能提升並支援服務端流式渲染

樣式元件與所有其他主流的 React CSS-in-JS 框架相比(淺紅色是:v3.0.2;深紅色是:v3.1.0)

在更細緻測試中,雖然它不是(還不是)最快的 CSS-in-JS 框架,但它只比那些最快的框架慢少許 ——  關鍵的是它不再是瓶頸。現實的使用結果是最鼓舞人心的,我們已迫不及待的等你們都來報告你們的發現了!

服務端流式渲染

在 React v16 中有介紹服務端流式渲染。在 React 還在渲染的時候,它允許應用程式伺服器傳送部分 HTML 作為可用頁面,這有助於 更快的首屏渲染(TTFB),也允許你的 Node 伺服器***更容易***處理後端壓力

但不能和 CSS-in-JS 相容:傳統上,在 React 完成渲染後,我們會在所有元件樣式的 <head> 中注入一個 <style> 標籤。然而,在流式傳輸的情況下,在所有元件渲染前,<head> 就已傳送到使用者端,所以我們不能再注入樣式。

解決方案是在元件被渲染的時候,插入帶 **<style>** 的 HTML,而不是等到再一次性注入所有元件。由於那樣會在客戶端上造成 ReactDOM 混亂( React 不再對現在的 HTML 負責),所以我們在客戶端再重構前將所有這些 style 標籤重新合併到 <head> 中。

我們已經實現了這一點;你可以在樣式元件中使用服務端流式渲染 以下是使用方法:

import { renderToNodeStream } from 'react-dom/server'
import styled, { ServerStyleSheet } from 'styled-components'
res.write('<!DOCTYPE html><html><head><title>My Title</title></head><body><div id="root">')
const sheet = new ServerStyleSheet()
const jsx = sheet.collectStyles(<App />)
// Interleave the HTML stream with <style> tags
const stream = sheet.interleaveWithNodeStream(
  renderToNodeStream(jsx)
)
stream.pipe(res, { end: false })
stream.on('end', () => res.end('</div></body></html>'))
複製程式碼

稍後在客戶端,我們必須呼叫 consolidateStreamedStyles() API 為 React 的再重構階段做準備:

import ReactDOM from 'react-dom'
import { consolidateStreamedStyles } from 'styled-components'
/* Make sure you call this before ReactDOM.hydrate! */
consolidateStreamedStyles()
ReactDOM.hydrate(<App />, rootElem)
複製程式碼

這裡就是它的所有了!?(檢視流式文件瞭解更多資訊)

v3:無縫更新

好訊息!如果你使用的是 v2 版本(或者甚至是 v1 版本),新版本是向後相容的,應該是無縫升級。這些新版本已加入了許多改進,所有請看一看,我們希望你和你的訪客能夠享受它們!

有關 v3.0.0 和 v3.1.0 發行版更多的資訊,請參閱更新日誌

緊隨潮流! ?


可以在樣式化元件社群中討論這篇文章

感謝 Gregory Shehet 提出的 CSS-in-JS benchmarks 為這篇文章提供了參考。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章