Help
Support Us

Server-Side Rendering

Server-Side Rendering (often abbreviated as "SSR") allows you to render your application to an HTML string that can be sent to the client to improve load time. Outside of that there are other scenarios, like testing, where SSR proves really useful.



Installation

The server-side renderer for Preact lives in its own repository and can be installed via your packager of choice:

npm install -S preact-render-to-string

After the command above finished, we can start using it right away.

HTML Strings

Both of the following options return a single HTML string that represents the full rendered output of your Preact application.

renderToString

The most basic and straightforward rendering method, renderToString transforms a Preact tree into a string of HTML synchronously.

import { renderToString } from 'preact-render-to-string';

const name = 'Preact User!'
const App = <div class="foo">Hello {name}</div>;

const html = renderToString(App);
console.log(html);
// <div class="foo">Hello Preact User!</div>

renderToStringAsync

Awaits the resolution of promises before returning the complete HTML string. This is particularly useful when utilizing suspense for lazy-loaded components or data fetching.

// app.js
import { Suspense, lazy } from 'preact/compat';

const HomePage = lazy(() => import('./pages/home.js'));

function App() {
  return (
    <Suspense fallback={<p>Loading</p>}>
      <HomePage />
    </Suspense>
  );
};
import { renderToStringAsync } from 'preact-render-to-string';
import { App } from './app.js';

const html = await renderToStringAsync(<App />);
console.log(html);
// <h1>Home page</h1>

Note: Unfortunately there's a handful of known limitations in Preact v10's implementation of "resumed hydration" — that is, hydration that can pause and wait for JS chunks or data to be downloaded & available before continuing. This has been solved in the upcoming Preact v11 release.

For now, you'll want to avoid async boundaries that return 0 or more than 1 DOM node as children, such as in the following examples:

function X() {
  // Some lazy operation, such as initializing analytics
  return null;
};

const LazyOperation = lazy(() => /* import X */);
function Y() {
  // `<Fragment>` disappears upon rendering, leaving two `<p>` DOM elements
  return (
    <Fragment>
      <p>Foo</p>
      <p>Bar</p>
    </Fragment>
  );
};

const SuspendingMultipleChildren = lazy(() => /* import Y */);

For a more comprehensive write up of the known problems and how we have addressed them, please see Hydration 2.0 (preactjs/preact#4442)

HTML Streams

Streaming is a method of rendering that allows you to send parts of your Preact application to the client as they are ready rather than waiting for the entire render to complete.

renderToPipeableStream

renderToPipeableStream is a streaming method that utilizes Node.js Streams to render your application. If you are not using Node, you should look to renderToReadableStream instead.

import { renderToPipeableStream } from 'preact-render-to-string/stream-node';

// Request handler syntax and form will vary across frameworks
function handler(req, res) {
  const { pipe, abort } = renderToPipeableStream(<App />, {
    onShellReady() {
      res.statusCode = 200;
      res.setHeader('Content-Type', 'text/html');
      pipe(res);
    },
    onError(error) {
      res.statusCode = 500;
      res.send(
          `<!doctype html><p>An error ocurred:</p><pre>${error.message}</pre>`
      );
    },
  });

  // Abandon and switch to client rendering if enough time passes.
	setTimeout(abort, 2000);
}

renderToReadableStream

renderToReadableStream is another streaming method and similar to renderToPipeableStream, but designed for use in environments that support standardized Web Streams instead.

import { renderToReadableStream } from 'preact-render-to-string/stream';

// Request handler syntax and form will vary across frameworks
function handler(req, res) {
  const stream = renderToReadableStream(<App />);

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

Customize Renderer Output

We offer a number of options through the /jsx module to customize the output of the renderer for a handful of popular use cases.

JSX Mode

The JSX rendering mode is especially useful if you're doing any kind of snapshot testing. It renders the output as if it was written in JSX.

import renderToString from 'preact-render-to-string/jsx';

const App = <div data-foo={true} />;

const html = renderToString(App, {}, { jsx: true });
console.log(html);
// <div data-foo={true} />

Pretty Mode

If you need to get the rendered output in a more human friendly way, we've got you covered! By passing the pretty option, we'll preserve whitespace and indent the output as expected.

import renderToString from 'preact-render-to-string/jsx';

const Foo = () => <div>foo</div>;
const App = <div class="foo"><Foo /></div>;

const html = renderToString(App, {}, { pretty: true });
console.log(html);
// <div class="foo">
//   <div>foo</div>
// </div>

Shallow Mode

For some purposes it's often preferable to not render the whole tree, but only one level. For that we have a shallow renderer which will print child components by name, instead of their return value.

import renderToString from 'preact-render-to-string/jsx';

const Foo = () => <div>foo</div>;
const App = <div class="foo"><Foo /></div>;

const html = renderToString(App, {}, { shallow: true });
console.log(html);
// <div class="foo"><Foo /></div>

XML Mode

For elements without children, XML mode will instead render them as self-closing tags.

import renderToString from 'preact-render-to-string/jsx';

const Foo = () => <div></div>;
const App = <div class="foo"><Foo /></div>;

let html = renderToString(App, {}, { xml: true });
console.log(html);
// <div class="foo"><div /></div>

html = renderToString(App, {}, { xml: false });
console.log(html);
// <div class="foo"><div></div></div>

Built by a bunch of lovely people like @Connormiha.