Embed binary data inside an HTML file in an efficient way.
Sometimes, your script requires some binary data that is available at compile time,
and that you would like to inline in order to reduce the number of network roundtrips.
You could inline this data directly inside your script, as a new Uint8Array([...])
,
but this would greatly increase your script's parse time, and the amount of data transferred.
Here, we propose a better alternative: package the binary data as an inline PNG image. The browser can load the inline image without blocking the JavaScript code, and you benefit from the deflate compression provided by the PNG format.
You can see a full example of how to use bin2png
and png2bin
with an external build tool (in this case, parcel) in the example/
folder.
Install bin2png in your dev dependencies (you only need it to build your html file):
npm install --save-dev bin2png
You can use the bin2png CLI tool that is provided with the npm package:
npx bin2png file.bin encoded.png
From a build script, you can use:
const bin2png = require("bin2png").bin2png;
// bin2png takes an Uint8Array and returns another Uint8Array
const pngData = await bin2png(binaryData);
Add png2bin to your normal dependencies:
npm install png2bin
Then use the png2bin
function from the package to decode the image:
<img id="myfile"
decoding="async" loading="eager"
style="display:none"
src="data:image/png;base64,..." />
import { png2bin } from "png2bin";
const img = document.getElementById("myfile");
const mydata = await png2bin(img);
// mydata is now an Uint8Array with the contents of the original file
Some browser privacy settings alter canvas pixels or prevent reading data from canvases altogether. This is the case of the Tor browser and Brave when anti-tracking protections are activated. This will prevent png2bin from working in these browsers. For more information, see brave/brave-browser#14421.