Skip to content
This repository was archived by the owner on Feb 5, 2022. It is now read-only.

shawnbot/streaming-react-renderer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Streaming React renderer

This is proof of concept that demonstrates one way to stream HTML and render specific elements as React components. Why would you want to do that? Here are a couple of reasons:

  1. Your application servers don't/can't/won't run Node.
  2. You run Rails, but you've discovered that the official react-rails project is just not usable in its current form because it completely breaks React's composition model.
  3. You don't use React, but are interested in seeing how a component-driven architecture could focus your teams' efforts on building features rather than copy-pasting gigantic blobs of HTML or maintaining unwieldy templates.

This approach suggests a form of server-side includes with a React-flavored twist.

Example

Here's what it looks like in practice:

const createTransformStream = require('streaming-react-renderer')
const componentMap = require('path/to/my/components')

const transform = createTransformStream(componentMap)

process.stdin
  .pipe(transform)
  .pipe(process.stdout)

The componentMap is an object literal that maps HTML element names to React component classes (or functions, or whatever). For instance, if your component map were exported via the following (assuming that this was pre-compiled to vanilla ES6 with Babel!):

import React from 'react'
export default {
  'primer-box': ({children}) => <div className='Box'>{children}</div>
}

Given those two files, you would be able to pipe in the following:

<primer-box>
  <h3>Hello, world!</h3>
</primer-box>

and get:

<div class="Box">
  <h3>Hello, world!</h3>
</div>

Things to note:

  • This uses htmlparser2, an event-based HTML/XML parser with support for preserving element and attribute case (which is important when passing through case-sensitive bits like viewBox). In theory, you could use elemets like <Box> to match up 1:1 with React.
  • Only the elements named in your component map are rendered with React. Once the parser reaches the close of a component tag, it resumes streaming the (hopefully) unmodified markup.
  • HTML attributes are passed through directly as props, which means that everything is a string. We could use propTypes to infer their types and coerce them to, numbers, arrays (parse as JSON?), etc. One big limitation is that we wouldn't be able to pass functions (e.g. for event listeners) without using eval().
  • This uses ReactDOMServer's renderToStaticMarkup() as opposed to renderToString(), which means that it can't be rehydrated, but that could change!
  • It's pretty fast, and the pass-through HTML streaming could probably be made a lot faster.

About

[proof of concept] A transform stream that renders certain elements as React components

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors