Git Product home page Git Product logo

hyperapp-render's Introduction

Hyperapp Render

npm version npm downloads library size discord chat

This library is allowing you to render Hyperapp views to an HTML string.

  • User experience — Generate HTML on the server and send the markup down on the initial request for faster page loads. Built-in mounting feature in Hyperapp is allowing you to have a very performant first-load experience.
  • Accessibility — Allow search engines to crawl your pages for SEO purposes.
  • TestabilityCheck HTML validity and use snapshot testing to improve quality of your software.

Getting Started

Our first example is an interactive app from which you can generate an HTML markup. Go ahead and try it online.

import { h } from 'hyperapp'
import { renderToString } from 'hyperapp-render'

const state = {
  text: 'Hello'
}

const actions = {
  setText: text => ({ text })
}

const view = (state, actions) => (
  <main>
    <h1>{state.text.trim() === '' ? '👋' : state.text}</h1>
    <input value={state.text} oninput={e => actions.setText(e.target.value)} />
  </main>
)

const html = renderToString(view(state, actions))

console.log(html) // => <main><h1>Hello</h1><input value="Hello"/></main>

Looking for a boilerplate? Try Hyperapp Starter with pre-configured server-side rendering and many more.

Installation

Using npm:

npm install hyperapp-render --save

Or using a CDN like unpkg.com or jsDelivr with the following script tag:

<script src="https://unpkg.com/hyperapp-render"></script>

You can find the library in window.hyperappRender.

We support all ES5-compliant browsers, including Internet Explorer 9 and above, but depending on your target browsers you may need to include polyfills for Set and Map before any other code.

Usage

The library provides two functions which you can use depending on your needs or personal preferences:

import { renderToString, renderToStream } from 'hyperapp-render'

renderToString(<Component />)        // => <string>
renderToString(view(state, actions)) // => <string>
renderToString(view, state, actions) // => <string>

renderToStream(<Component />)        // => <stream.Readable> => <string>
renderToStream(view(state, actions)) // => <stream.Readable> => <string>
renderToStream(view, state, actions) // => <stream.Readable> => <string>

Note: renderToStream is available from Node.js environment only (v6 or newer).

Overview

You can use renderToString function to generate HTML on the server and send the markup down on the initial request for faster page loads and to allow search engines to crawl your pages for SEO purposes.

If you call hyperapp.app() on a node that already has this server-rendered markup, Hyperapp will preserve it and only attach event handlers, allowing you to have a very performant first-load experience.

The renderToStream function returns a Readable stream that outputs an HTML string. The HTML output by this stream is exactly equal to what renderToString would return. By using this function you can reduce TTFB and improve user experience even more.

Caveats

The library automatically escapes text content and attribute values of virtual DOM nodes to protect your application against XSS attacks. However, it is not safe to allow "user input" for node names or attribute keys:

const Node = 'div onclick="alert()"'
renderToString(<Node title="XSS">Hi</Node>)
// => <div onclick="alert()" title="XSS">Hi</div>

const attributes = { 'onclick="alert()" title': 'XSS' }
renderToString(<div {...attributes}>Hi</div>)
// => <div onclick="alert()" title="XSS">Hi</div>

const userInput = '<script>alert()</script>'
renderToString(<div title="XSS" innerHTML={userInput}>Hi</div>)
// => <div title="XSS"><script>alert()</script></div>

License

Hyperapp Render is MIT licensed. See LICENSE.

hyperapp-render's People

Contributors

casperin avatar dependabot[bot] avatar developerdizzle avatar frenzzy avatar joseluisq avatar kwasniew avatar loteoo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

hyperapp-render's Issues

Error: Cannot find module 'hyperapp-render/browser'

In a recent update it looks like the import name was broken or changed. What's the alternative to this import now? Is this still the correct way?

import { renderToString } from 'hyperapp-render/browser'

I didn't see anything in release notes but I did see quite a few updates in package.json so I'm unsure.

Usage of innerHTML

Hi, I'm working on a simple component to insert (markdown generated) html into an element using the oncreate and onupdate lifecycle hooks. Everything seemed ok until I viewed the source of the page and noticed the innerHTML wasn't being rendered on the server since oncreate only triggers after the element has been created.

Since we kind of need it for SEO, I tried a couple of things and found out that adding an innerHTML attribute/prop does render it on the server, although that doesn't work client-side.

I am not sure if this is intentional or a bug, since I couldn't find it anywhere in the documentation. Is this the way go or can we expect it to be gone in a next release?

const setHtml = (html: string) => (el: HTMLElement) => el.innerHTML = html;

const UnsafeHtml = ({ html, tag = 'div' }: Props) =>
  h(tag, {
    innerHTML: html, // ssr only?
    oncreate: setHtml(html),
    onupdate: setHtml(html),
  });

Usage with Hyperapp 2

I'm submitting a ...

  • bug report
  • feature request
  • other (Please do not submit support requests here (below))

Documentation request

It looks like the readme shows usage with Hyperapp 1? I can't really figure out how to do this with Hyperapp 2.

renderToNode (or renderToElement)

Hi,

I'm submitting a ...

  • bug report
  • feature request
  • other (Please do not submit support requests here (below))

Within hyperapp sometimes I need to make some preparations, to ensure everything is going fine with DOM/events/data. For example:

  1. generate <video> element, append some sources, and check which one browser wants to load;
  2. create <img> element and check if image is accessible and what size they have;
  3. insert svg fragment into already loaded though <object> tag svg dom.

It is really useful to have function, which renders h('video', ...) into new Element, which can be inserted into existing DOM or just loaded (like images or videos), because as of now my preparations looks like

const el = document.createElement('video');
el.addEventListener('loadeddata', this.onVideoLoad.bind(this), false);
el.addEventListener('abort', this.onVideoAbort.bind(this), false);
el.addEventListener('waiting', this.onVideoWaiting.bind(this), false);
el.addEventListener('loadedmetadata', this.onVideoMeta.bind (this), false);
el.setAttribute('preload', 'metadata');
el.setAttribute('muted', 'true');
el.setAttribute('playsinline', 'true');
this.config.sources.forEach(source => {
	var srcEl = document.createElement('source');
	srcEl.src = patchLocalVideo(source.url);
	srcEl.type = source.type;
	el.appendChild(srcEl);
});

I can implement it myself and make a pull request if you're interested in this.

Broken support for ^2.0.9

I'm submitting a ...

  • bug report
  • feature request
  • other (Please do not submit support requests here (below))

Description of the bug

hyperapp-render will not work with anything newer than 2.0.9 (included). This is because the creator of hyperapp made a commit where he switched the name of two keys in the vdom object, see commit 8e6a4908954186ed8466ae9ef15ec172ddbea2d0.

Steps to reproduce

import { renderToString } from 'hyperapp-render'
import { h, text } from 'hyperapp'

console.log(renderToString(h("p", {}, text("Hello World!")))) // output: undefined

With version 2.0.9 the output is: undefined

Expected output

With version 2.0.8 the output of the snippet in the section above is: <p>Hello World!</p>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.