npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

preact-render-to-stream

v0.0.5

Published

Render preact to an html stream with out of order deferred slots

Downloads

22

Readme

preact-render-to-stream

NPM
version

Render JSX and Preact components to an HTML stream with out of order deferred elements.

Demo: https://preact-render-to-stream.olofbjerke.com

Note: This is still an experimental package and the API is not stable yet.

If you use preact for dynamic server side rendering (SSR), then this package can help with First Contentful Paint, as it can defer parts of the UI to be streamed in later in the HTTP response.

The package uses the preact-render-to-string package to render the HTML and a special context to defer parts of the UI until their lazy data is ready to be rendered.

This package is inspired by the Flecks library for Ruby.

The package is written in TypeScript and is published as a ES module with type definitions.

Installation

npm install preact-render-to-stream

Usage

No server framework

import http from "node:http";
import { toStream, DefaultHead, Defer } from "preact-render-to-stream";

const server = http.createServer(async (req, res) => {
    res.writeHead(200, { "Content-Type": "text/html" });

    const stream = toStream(
        <DefaultHead />,
        <>
            <header>
                <h1>preact-render-to-stream demo</h1>
            </header>
            <main>
                <Defer
                    promise={new Promise((res) => setTimeout(() => res("Got data"), 1500))}
                    fallback={() => <p>Loading</p>}
                    render={(d) => <p>{d}</p>}
                />
                <p>This is shown even though the previous component is slow.</p>
            </main>
        </>
    );

    for await (const part of stream) {
        res.write(part);
    }

    res.end();
});

server.listen(8000);

Fastify

Fastify accepts a stream as response, so we can use the toStream function to render the HTML stream and pass it to the reply.

import Fastify from "fastify";
import { toStream, DefaultHead, Defer } from "preact-render-to-stream";

const fastify = Fastify({
    logger: true,
});

fastify.get("/", async function (request, reply) {
    reply.header("Content-Type", "text/html");

    const stream = toStream(
        <DefaultHead title="preact-render-to-stream demo">
            <link rel="stylesheet" async href="/public/main.css" />
            <script async type="module" src="/public/main.js"></script>
        </DefaultHead>,
        <>
            <header>
                <h1>preact-render-to-stream demo</h1>
            </header>
            <main>
                <Defer
                    promise={new Promise<string>((res) => setTimeout(() => res("Got data"), 1500))}
                    fallback={() => <p>Loading</p>}
                    render={(d) => <p>{d}</p>}
                />
                <p>This is shown even though the previous component is slow.</p>
            </main>
        </>
    );

    return reply.send(stream);
});

fastify.listen({ port: 8001 }, function (err, address) {
    if (err) {
        fastify.log.error(err);
        process.exit(1);
    }
});

API

toStream(head: VNode, body: VNode, endOfBody?: VNode): ReadableStream<unknown>

Renders the given JSX elements to an HTML stream.

<Defer /> component

Defers rendering of the given component until the promise is resolved. It adds a data-deferred-slot attribute to the fallback component, so that the deferred component can be inserted into the DOM later.

Props

  • promise: Promise<T>: The promise to wait for.
  • fallback: VNode: The component to render while the promise is pending.
  • render: (data: T) => VNode: The component to render when the promise is resolved.
  • onError: (error: unknown) => VNode: The component to render when the promise is rejected.

<DefaultHead /> component

Renders a set of default head tags and any additional tags passed as children.

Props

  • title: string: The title of the page.
  • children: ComponentChildren: Any tags to render inside the head.

License

MIT