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

react-dom-html

v1.4.0

Published

The easiest way to render Html applications using react

Downloads

16

Readme

react-dom-html

The easiest way to render full-page react-dom applications

It's react-dom, without the need for any html boilerplate

Supports React version 16+

npm npm CircleCI branch Maintainability Test Coverage Conventional Commits

Test coverage: ~98.5%

Contents

Introduction

react-dom-html is a thin wrapper around the client and server render methods of react-dom that takes care of all the html boilerplate.

If you want to define HTML metadata in your react application (similar to react-helmet), you can use react-dom-html-tags.

Browser methods supported:

  • renderHtml
  • hydrateHtml

Server methods supported:

  • renderHtmlToString
  • renderHtmlToStaticMarkup
  • renderHtmlToNodeStream
  • renderHtmlToStaticNodeStream
Bundle size:

~500 bytes gzipped for the client production build.

Install

// npm
npm install --save react-dom-html

// yarn
yarn add react-dom-html

Both react and react-dom are peer dependencies, so make sure you have them installed.

// npm
npm install --save react react-dom

// yarn
yarn add react react-dom

Usage

Browser

Client-side render

Use when renderHtmlToStaticMarkup, renderHtmlToStaticNodeStream or react-dom-html-cli is used to serve the application.

// browser.js
import {renderHtml} from "react-dom-html";
import MyApplication from "./MyApplication";

renderHtml(<MyApplication />);
Hydrate a server render

Use when renderHtmlToString or renderHtmlToNodeStream is used to serve the application.

// browser.js
import {hydrateHtml} from "react-dom-html";
import MyApplication from "./MyApplication";

// if the server rendered the page using react-dom-html you don't need to specify a container
hydrateHtml(<MyApplication />);

Server

Render to string
// server.js
import {renderHtmlToString, HTML5_DOCTYPE} from "react-dom-html/server";
import MyApplication from "./MyApplication";

// Render the app in a default html template
const html = renderHtmlToString(<MyApplication />);

// Using expressjs or another http framework
res.send(HTML5_DOCTYPE + html);
Render using node streams
import {renderHtmlToNodeStream, HTML5_DOCTYPE} from "react-dom-html/server";
import MyApplication from "./MyApplication";

const stream = renderHtmlToNodeStream(<App />);

res.write(HTML5_DOCTYPE);
return stream.pipe(res);

Server render options

Of course, you'll probably want to customize the Html and include your application bundle.

html: The simple option

The html option accepts a React component to render custom Html. The root element must be a <html> element.

The <app> element represents the application container where the application will be rendered in the HTML output. The <app> element must be defined in the html, and it must be an immediate child of the <body> element.

Optionally, you can customize the html tag used for the application container using the appContainerTagName option.

Here is a simple example:

// server.js
import {renderHtmlToString, HTML5_DOCTYPE} from "react-dom-html/server";
import MyApplication from "./MyApplication";


// The `<app />` element represents your application container.
// It's REQUIRED, and defines where your application will be rendered

// You can configure the html template using JSX
const html = renderHtmlToString(<MyApplication />, {
  html: (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <title>My Application</title>
      </head>
      <body className="pageBackground">

        {/*Include content before your application*/}
        <noscript>JavaScript must be enabled</noscript>

        {/*The `<app />` element is always REQUIRED*/}
        <app className="appBackground" />

        {/*Include content after your application*/}
        <script src="/public/scripts/appBundle.js" />

      </body>
    </html>
  ),

  // optionally, change the appContainer tag name
  appContainerTagName: "span"
}

// Using expressjs or another http framework
res.send(HTML5_DOCTYPE + html);

The html options also accepts a callback function that will be invoked after the application has rendered (for String rendering only). This enables you to assign content to the html output that is a result of the render

Here's a more complex example using the html option as a callback that is invoked after the application is rendered. This example includes:

import {renderHtmlToString, HTML5_DOCTYPE} from "react-dom-html/server";
import {ServerStyleSheet} from "styled-components";
import createReduxStore from './store';
import MyApplication from "./MyApplication";

const store = createReduxStore();
const sheet = new ServerStyleSheet();

const html = renderHtmlToString(sheet.collectStyles(<MyApplication />), {
    html: () => (
      // After the application is rendered, you can access styles created during the render
      const styleTags = sheet.getStyleElement();

      return (
        <html>
          <head>
              <meta charSet="utf-8" />
              <title>My Application</title>
              {styleTags}
          </head>
          <body>
            <app />

            {/*Serialize store data, and include bundle*/}
            <script dangerouslySetInnerHTML={__html: `__appData=${JSON.stringify(store.getState())};`} />
            <script src="/public/scripts/appBundle.js" />
          </body>
        </html>
      );
    )
});
htmlElements: The advanced option

Using the htmlElements options is slightly more complex but gives you much greater control of how the Html is rendered. This additional control is often required when rendering using streams.

You can use the above html option with streams when you do not need to serialize any state to the response (or write any other data to the response as a result of the application render). However, if you need to serialize state (or write other data to the response as a result of the application render) you must use the htmlElements option that enables element-specific callback(s) to be invoked. This allows you to serialize application state for the response.

If your application needs to render using both strings and streams with callbacks, you must use the htmlElements option.

IMPORTANT: The htmlElement and bodyElement options must not include any child elements.

Here is an example using all available htmlElements options:

import {renderHtmlToNodeStream, HTML5_DOCTYPE} from "react-dom-html/server";
import createReduxStore from './store';
import MyApplication from "./MyApplication";

const store = createReduxStore();

const stream = renderHtmlToNodeStream(<MyApplication />, {
    htmlElements: {
        htmlElement: <html lang="en" />,
        headElement: (
          <head>
            <meta charSet="utf-8" />
            <title>My Application</title>
          </head>
        ),
        headIsReactRoot: true,
        bodyElement: <body className="appBody" />,
        beforeAppContainerElement: <noscript>JavaScript must be enabled</noscript>,
        afterAppContainerElement: () => (
            <script dangerouslySetInnerHTML={__html: `__appData=${JSON.stringify(store.getState())};`} />
            <script src="/public/scripts/appBundle.js" />
        )
    }
});

Generating static Html

If you're not rendering your application on the server, you can still take advantage of react-dom-html to generate the .html page used to serve your application in the browser.

You can use react-dom-html-cli to generate .html files usin the same simple syntax. The cli utility makes it easy to integrate the html generator into your build process.

API

The API is very similar to react-dom, additional options have been added for sever methods.

If you're new to React, read the react-dom documentation first

Client

Unlike react-dom the container argument is optional for client methods if you used react-dom-html to generate the html used to render the app.

type renderCallback = () => void;

// Render the application in the browser

renderHtml(element: Element<any>, container?: DOMNode, callback?: renderCallback): void

// Hydrate the application in the browser

hydrateHtml(element: Element<any>, container?: DOMNode, callback?: renderCallback): void

Server

type renderElement = null | Element<any>;

type htmlElementOptions = {
  htmlElement?: Element<'html'> | () => Element<'html'>,
  headElement?: Element<'head'> | () => Element<'head'>,
  bodyElement?: Element<'body'> | () => Element<'body'>,
  appContainerElement?: Element<'*'> | () => Element<'*'>,
  beforeAppContainerElement?: Element<'*'> | () => Element<'*'>,
  afterAppContainerElement?: Element<'*'> | () => Element<'*'>,
  headIsReactRoot?: boolean = false
};

type serverRenderOptions = {
  html:? Element<'html'> | () => Element<'html'>,
  htmlElements:? htmlElementOptions | () => htmlElementOptions,
  appContainerTagName?: string = "div"
};

// Render to String

renderHtmlToString(element?: renderElement, options?: serverRenderOptions = {}): string

renderHtmlToStaticMarkup(element?: renderElement, options?: serverRenderOptions = {}): string

// Render to Node Stream

renderHtmlToNodeStream(element?: renderElement, options?: serverRenderOptions = {}): Stream

renderHtmlToStaticNodeStream(element?: renderElement, options?: serverRenderOptions = {}): Stream

Contribute

For questions or issues, please open an issue, and you're welcome to submit a PR for bug fixes and feature requests.

This package exists as a yarn workspace, you will need to fork and then clone the parent workspace. Follow the instructions in the workspace README file for installing the workspace dependencies.

Before submitting a PR, ensure you run npm test to verify that your code adheres to the configured lint rules and passes all tests. Be sure to include tests for any code changes or additions.

License

MIT