An experimental React component that performs expensive text measurements off the main thread and return results to the component's children.
Require ability to dynamically measure text for width, height, and other style attributes off-thread without interacting with DOM.
Three main concepts:
- WebWorker work is done off the main UI thread.
- With the introduction of OffscreenCanvas in Chrome 69, we can now perform Canvas work in a WebWorker.
- Inside a Canvas, you can do some powerful calculations on styles and positioning.
Let's combine these three concepts in the context of an application that does significant DOM or Canvas measuring. We can move these expensive calculations off the main thread by performing the same calculations inside a Canvas on a separate thread via a WebWorker. This will allow the main thread (UI thread) to free up resources, and allow the main thread to run smoothly and maintain a desired 60fps.
More details on OffscreenCanvas with WebWorkers can be found here
A React component that is able to handle expensive measurments of text attributes off-thread in a WebWorker, which then returns the requested measurements to the main thread for handing off to child components.
Clone the repo, install the dependencies, and run the dev environment. That's it!
git clone https://github.com/johnrjj/react-measure-text-worker.git
yarn install
yarn start
Navigate to localhost:1234 to see the app running
MeasureTextOffThread
renders a "child as a function" pattern which provides a textData object to the children, which the children can then use to render however they would like.
import { MeasureTextOffThread } from 'react-measure-text-off-thread';
const text = 'measure this text';
// inside render...
<MeasureTextOffThread
text={text}
fontSize={20}
fontFamily={'Arial'}
>
{textData => (
<span>
<div style={{ width: textData.width, height: textdata.height }}>
Do overlay here
</div>
<span>{text}</span>
</span>
)}
</MeasureTextOffThread>
βββββββββββββ
β β
β App β thread
β β boundary
βββββββββββββ
β β
β
β β
β postMessage βββββββββββββββββββ
βΌ request to β β β
βββββββββββββββββββββββββββ webworker β WebWorker β
β βββββββββββββββββββΌβββββΆβ onmessage ββββββββββββββββββββββ
β </MeasureTextOffThread> βββββββββββ β β βΌ
β β β β βββββββββββββββββββ ββββββββββββββββββββ¬ββββββ
βββββββββββββββββββββββββββ β β β β
β β β β Worker processes β LRU β
β β β request βcacheβ
β β β βββββββββββββββββββββββββββββ β β β
({ width, height }) β β β ββββββββββββββββββββ΄ββββββ
β β β β postMessage Response Bus β β
β ββββββββββββ (shared) βββββββββββββββ
βΌ β β β send response
βββββββββββββββββββββββββββ βββββββββββββββββββββββββββββ payload to bus
β β β
β children β
β β β
βββββββββββββββββββββββββββ
π₯ It's really fast.