Skip to content

A more elegant file compression and self-decompression solution #1776

@Caramel-Diode

Description

@Caramel-Diode

I think we can use the browser's native compression API to further reduce the file size. I know this might be more appropriate to raise as an issue in SingleFileZ.

Implementation

Compress the entire document content using the browser's gzip API

/**
 * @param {string} source ------ raw HTML
 * @return {Promis<string>} ---- Base64 Dataurl string
 */
const gzip = async source => {
    const reader = new FileReader();
    const cs = new CompressionStream("gzip");
    const writer = cs.writable.getWriter();
    writer.write(new TextEncoder().encode(source));
    writer.close();
    const blob = await new Response(cs.readable, { headers: { "Content-Type": "application/gzip" } }).blob();
    const { promise, resolve } = Promise.withResolvers();
    reader.addEventListener("load", resolve);
    reader.readAsDataURL(blob);
    await promise;
    return reader.result;
};

Use self-extracting code in the final saved file

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Loading...</title>
    <script type="module">
        const base64 = "...";// Generated by the gizp function
        const ds = new DecompressionStream("gzip");
        const writer = ds.writable.getWriter();
        writer.write(await (await fetch(base64)).arrayBuffer());
        writer.close();
        const rawHTML = await new TextDecoder().decode(await new Response(ds.readable).arrayBuffer())
        
        const doc = new DOMParser().parseFromString(rawHTML, "text/html");
        // Replace all the content within <html></html>
        // Using ` doc.documentElement.innerHTML ` in order to remove `<!DOCTYPE html>` Document declaration node
        document.documentElement.innerHTML = doc.documentElement.innerHTML; 
        // We don't need to use JavaScript....
        // Function(doc.querySelector("script").textContent)();
        // dispatchEvent(new Event("DOMContentLoaded"));
    </script>
</head>
<body>
    <noscript>Enable JavaScript to display content properly</noscript>
</body>
</html>

The above operations can reduce the file size by about 40%, which is particularly effective for text content.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions