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

create-render-4r

v3.1.2

Published

Express.js middleware to render a React+Router+Redux+Radium app

Downloads

5

Readme

Universal render for React+ Build Status

Express.js middleware to render a 4r app server-side:

Diagram: Universal Web Apps & create-render-4r

Features

Example Universal Web App

Demonstrates using this renderer in a working universal app.

Install

Add the module to package.json:

npm install create-render-4r --save

# Save peer dependencies for production (otherwise they're only dev dependencies):
npm install [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] --save

Upgrading

Breaking changes are indicated by major versions. See UPGRADING

Usage

Basic usage in an Express server.js:

var express = require('express');
var createRender4r = require('create-render-4r');

var app = express();

// These are unique to your own app.
var routes = require('./my-routes');
var loadStore = require('./my-load-store');
var layoutHtml = require('./my-layout-html');

// Create the render middleware.
var render4r = createRender4r({
  routes:       routes,
  loadStore:    loadStore,
  layoutHtml:   layoutHtml
});

// Add the render for all requests.
app.use(render4r);

var PORT = process.env.PORT || 3000;
app.listen(PORT, function () {
  console.log('Server listening on', PORT);
});

Example server.js

API

createRender4r()

This function is used to generate the Express.js middleware.

It accepts a single argument, an object:

createRender4r({ routes, loadStore, layoutHtml, decorateResponse })

routes

(Required) The <Router/> component

loadStore

(Required) A function taking initial state, returning the Redux store; created with Redux createStore

var Redux = require('redux');
var createStore = Redux.createStore;
var combineReducers = Redux.combineReducers;

var reducers = './my-reducers';

function loadStore(initialState) {
  return createStore(combineReducers(reducers), initialState);
}

layoutHtml

(Required) An HTML template function; this sample uses ES2015 module & template string syntx:

function layoutHtml(componentHTML, cleanInitialState, documentMeta) {
  return `
    <!DOCTYPE html>
    <html>
      <head>
        ${documentMeta}

        <script type="application/javascript">
          window.__INITIAL_STATE__ = ${cleanInitialState};
        </script>
      </head>
      <body>
        <div id="react-view">${componentHTML}</div>

        <script type="application/javascript" src="/bundle.js"></script>
      </body>
    </html>
  `;
}

decorateResponse

(Optional) A side-effect function to update the response based on state:

function decorateResponse(res, state) {
  /*
  Example: set 404 response status when the item couldn't be fetched,
    while the app still renders a nice Not Found message in the UI.
  */
  var errText = state.item.get('error');
  if (errText && /^404/.exec(errText)) {
    res.status(404)
  }
}

Example createRender4r()

Server-side async data loading

Per-component data loading for the current route.

fetchData()

Define this static (class) method on React components to enable Promise-based server-side fetching. You'll need to use a universal library like isomorphic-fetch within redux-thunk async action creators so they will work equivalently on the server-side & in web browsers.

fetchData(dispatch, props)

  • dispatch (required) the Redux store's dispatcher
  • props (required) the component's props

Must return a Promise to await completetion of the fetch. (This is what Redux thunk does.)

static fetchData(dispatch, props) {
  return dispatch(ItemActions.getItem(props.params.id));
}

Example fetchData()

sagasToRun()

Define this static (class) method on React components to enable Generator-based server-side fetching via Redux sagas.

sagasToRun(dispatch, props)

  • dispatch (required) the Redux store's dispatcher
  • props (required) the component's props

Must return an array of arrays of arguments for middleware.run.

static sagasToRun(dispatch, props) {
  return [
    [fetchThingsSaga],
    [verifyAuthSaga, { userId: props.params.authUserId }]
  ];
}

Additionally, the Redux store returned by loadStore() must expose the Saga middleware as store.sagaMiddleware:

// …
import createSagaMiddleware       from 'redux-saga';
// …

export default function loadStore(...createStoreRestParams) {
  const sagaMiddleware            = createSagaMiddleware(...sagas);
  // …
  // This accessor must be added for Saga middleware to be used server-side:
  store.sagaMiddleware            = sagaMiddleware;
  return store;
}

Absolute URLs

Frequently, app code will need its absolute URL, canonical hostname & protocol to render links or make API requests.

This module includes a sourceRequest reducer to handle this state. It is captured on the server for each request as the Redux store is initialized.

Example state.sourceRequest.host values:

  • localhost:3000
  • example.com
  • api.example.com:8443
  • velvet-glacier-1234.herokuapp.com

Example state.sourceRequest.protocol values:

  • https
  • http

To use these values in an app:

  1. Add this module's reducers to your store:
import { combineReducers } from 'redux'
import { reducers as cr4rReducers } from 'create-render-4r'

const rootReducer = combineReducers(
  Object.assign(
    cr4rReducers,
    // …& the app's reducers
  )
)

Example reducers/index.js

  1. Then access it in the Redux state:
// `store` is the Redux store
const state = store.getState();
const proto = state.sourceRequest.protocol;
const host = state.sourceRequest.host;

Example actions/counter.js