New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@ssrx/renderer

Package Overview
Dependencies
Maintainers
0
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ssrx/renderer

The SSRx renderer establishes some patterns to hook into the lifecycle of streaming SSR apps in a framework/library agnostic way. It is client and server framework agnostic, so long as the server runtime supports web streams and AsyncLocalStorage (node 18

  • 0.5.1
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
475
decreased by-39.87%
Maintainers
0
Weekly downloads
 
Created
Source

@ssrx/renderer

The SSRx renderer establishes some patterns to hook into the lifecycle of streaming SSR apps in a framework/library agnostic way. It is client and server framework agnostic, so long as the server runtime supports web streams and AsyncLocalStorage (node 18+, bun, deno, cloudflare, vercel, etc). A handful of renderer plugins for common libraries are maintained in this repo.

See the react-router-kitchen-sink and remix-vite examples for a look at how everything can work together in practice.

Usage

@ssrx/renderer exports a createApp function that allows you to compose all the pieces necessary to render a SSR streamed application.

An example with React (Solid works almost exactly the same):

src/app.tsx
// In this case we're using the `react` renderer, which simply wraps @ssrx/renderer with a react specific stream function
import { createApp } from '@ssrx/react';
import { assetsPlugin } from '@ssrx/renderer/assets';

export const { clientHandler, serverHandler, ctx } = createApp({
  // Usually a router plugin will provide the appRenderer, but you can always provide your own if needed
  appRenderer:
    ({ req }) =>
    () =>
      <div>My App</div>,

  plugins: [
    // If you are also using `@ssrx/vite`, this plugin automatically injects js/css assets into your html stream
    assetsPlugin(),

    // ... your plugins, or 3rd party plugins. More on the plugin shape below
  ],
});
src/entry.client.tsx
import { hydrateRoot } from 'react-dom/client';

import { clientHandler } from './app.tsx';

void hydrate();

async function hydrate() {
  const app = await clientHandler();

  hydrateRoot(document, app());
}
src/server.ts
import { serverHandler } from '~/app.tsx';

export default {
  fetch(req: Request) {
    const { stream, statusCode } = await serverHandler({ req });

    return new Response(stream, { status: statusCode(), headers: { 'Content-Type': 'text/html' } });
  },
};

With the above steps you get a streaming react app with support for lazy asset preloading. However, plugins are where @ssrx/renderer really shines.

Plugins

Plugins can:

  • Hook into the client and server rendering in a standardized way
  • Extend a typesafe ctx object that is made available on the client and the server, even outside of the rendering tree (for example in router loader functions). This is accomplished via a proxy that is exposed on the window in the client context, and via async local storage on the server.

Plugin Shape

See the renderer types file for the full plugin signature.

export type RenderPlugin = {
  id: string;

  /**
   * Called once per request.
   */
  hooksForReq: (props: {
    req: Request;
    meta?: SSRx.ReqMeta;
    renderProps: SSRx.RenderProps;
    ctx: Record<string, unknown>;
  }) => {
    // Called on the client and the server
    common?: {
      /**
       * Extend the app ctx object with additional properties. Consider this "external" context - it is made available
       * to the end application on the server and the client.
       */
      extendAppCtx?: () => Record<string, unknown>;

      /**
       * Wrap the app component with a higher-order component. This is useful for wrapping the app with providers, etc.
       */
      wrapApp?: (props: { children: () => Config['jsxElement'] }) => Config['jsxElement'];

      /**
       * Render the final inner-most app component. Only one plugin may do this - usually a routing plugin.
       */
      renderApp?: () => (() => Config['jsxElement']) | Promise<() => Config['jsxElement']>;
    };

    // Only called on the server
    server?: {
      /**
       * Return a string to emit some HTML into the SSR stream just before the document's closing </head> tag.
       *
       * Triggers once per request.
       */
      emitToDocumentHead?: Promise<string | undefined> | string | undefined;

      /**
       * Return a string to emit into the SSR stream just before the rendering
       * framework (react, solid, etc) emits a chunk of the page.
       *
       * Triggers one or more times per request.
       */
      emitBeforeStreamChunk?: Promise<string | undefined> | string | undefined;

      /**
       * Return a string to emit some HTML to the document body, after the client renderer's first flush.
       *
       * Triggers once per request.
       */
      emitToDocumentBody?: Promise<string | undefined> | string | undefined;

      /**
       * Runs when the stream is done processing.
       */
      onStreamComplete?: Promise<void> | void;
    };
  };
};

Directory

PackageRelease Notes
@ssrx/renderer@ssrx/renderer version
@ssrx/react@ssrx/react version
@ssrx/remix@ssrx/remix version
@ssrx/solid@ssrx/solid version
@ssrx/streaming@ssrx/streaming version
@ssrx/trpc-react-query@ssrx/trpc-react-query version
@ssrx/plugin-react-router@ssrx/plugin-react-router version
@ssrx/plugin-solid-router@ssrx/plugin-solid-router version
@ssrx/plugin-tanstack-query@ssrx/plugin-tanstack-query version
@ssrx/plugin-tanstack-router@ssrx/plugin-tanstack-router version
@ssrx/plugin-trpc-react@ssrx/plugin-trpc-react version
@ssrx/plugin-unhead@ssrx/plugin-unhead version

FAQs

Package last updated on 29 Sep 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc