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

jsxpress

v0.0.1

Published

Server-Side JSX Router

Downloads

12

Readme

#jsXpress

Router for Server Side Rendering of JSX (React)

##About

jsXpress is middleware for express/connect that allows for server-side rendering of elements written in react.

##JSX Syntax The examples below are written using JSX syntax, but OTHER SYNTAX should work perfectly fine. If you would like to work with JSX syntax, there are many WAYS TO DO IT

##Installation

To install jsxpress in your local project, simply type

npm install --save jsxpress

To reference jsxpress in your project

var jsXpress = require('jsxpress');

##Getting Started

Using jsXpress with an express or connect application is easy. Simply place it on a route where you would normally place and pass it a react element.

var React = require('React');
var app = require('express')();
...
app.get('*', jsXpress(
    <html renderat='/'>
      <body>
        Hello World
      </body>
    </html>
)

Notice the renderat attribute. It's set to '/', which means that the given component will render at the root of your application. If you were to leave this out, you application would not render.

If you wanted to have a choice between pages, you could put two element with the renderat attribute set side by side. Since you react requires adjacent components to be nexted, you'll have to wrap them in another element, but as long as it doesn't have a renderat attribute, it won't render.

app.get('*', jsXpress(
    <html>
      <html renderat='/'>
        <body>
          Hello World
        </body>
      </html>
      <html renderat='/signin'>
        <body>
          Sign In
        </body>
      </html>
    </html>
);

It won't really affect how your code works, but if you're uncomfortable using react components in such a way, you can use the jsXpress.NoRender component instead.

app.get('*', jsXpress(
    <jsXpress.NoRender>
      <html renderat='/'>
        <body>
          Hello World
        </body>
      </html>
      <html renderat='/signin'>
        <body>
          Sign In
        </body>
      </html>
    </jsXpress.NoRender>
);

##Using Custom Components

You can easily use mix and match components, even custom ones.

class SignInPage extends React.Component{
  constructor(){
  }
  render(){
    <html renderat='/signin'>
      <body>
        Sign In
      </body>
    </html>
  }
}

app.get('*', jsXpress(
    <jsXpress.NoRender>
      <html renderat='/'>
        <body>
          Hello World
        </body>
      </html>
      <SignInPage renderat='signin' />
    </jsXpress.NoRender>
);

##Prerendering elements

The rendering of elements can be pre-empted by assiging a function with a prerender attribute. The function has access to the element, the httprequest, and the http response. It should return a modified copy of the element to be rendered.

var preRenderer = function(element, request, response){
  return React.cloneElement(element, {message:"Hello Universe!"});
}

class WelcomePage extends React.Component{
  constructor(props){
    this.state = {
      messate : props.message || "Hello World"
    }
  }
  render(){
    <html renderat='/signin'>
      <body>
        {this.state.message}
      </body>
    </html>
  }
}

...

app.get('*', jsXpress(
    <jsXpress.NoRender>
      <WelcomePage renderat= '/' prerender={preRenderer}/>
      <SignInPage renderat='signin' />
    </jsXpress.NoRender>
);

##Accessing Parametes Non-rendred pages can heiarchically define routes with the renderthrough attribute.

class AboutPage extends React.Component{
  constructor(props){
    this.state = {
      text : props.text || "Lear About Us"
    }
  }
  render(){
    <html renderat='/signin'>
      <body>
        {this.state.message}
      </body>
    </html>
  }
}

app.get('*', jsXpress(
    <jsXpress.NoRender>
      <WelcomePage renderat= '/' prerender={preRenderer}/>
      <SignInPage renderat='signin' />
      <jsXpress.NoRender renderthrough="about">
        <AboutPage renderat='/' ></AboutPage>
        <AboutPage renderat='team' text='Who we are... '></AboutPage>
        <AboutPage renderat='whatwedo' text='What we do...'></AboutPage>
      </jsXpress.NoRender>
    </jsXpress.NoRender>
);

Here, a page showing 'What we do' can be found by visiting /about/whatwedo

##Route Parames

Route params are available as well. You can make them accessible in the request object during the prerender stage, by passing in the routeParams option.

var nameRenderer = function(element, request){
  return React.cloneElement(
    element,
    {text : "Your name is " + request.routeParams.name}} + ".");
}

app.get('*', jsXpress(
    <jsXpress.NoRender>
      <WelcomePage renderat= '/' prerender={preRenderer}/>
      <SignInPage renderat='signin' />
      <jsXpress.NoRender renderthrough="about">
        <AboutPage renderat='/' ></AboutPage>
        <AboutPage renderat='team' text='Who we are... '></AboutPage>
        <AboutPage renderat='whatwedo' text='What we do...'></AboutPage>
        <AboutPage renderat=':name' prerender={nameRenderer}></AboutPage>
      </jsXpress.NoRender>
    </jsXpress.NoRender>,
    {routeParams:true}
);

Learn a bit about yourself by visiting /about/...

##Middleware

You can use other just like you would in any other connect or express application. Because the request, response, and next objects from the express/connect router are attached to each components props object when rendering, JSX component can act like middleware by manipulating these in their constructors.

class LoggerMiddleware Extends React.Component{
  constructor(props){
    var request = props.request;
    var response = props.response;
    var next = props.next();
    console.log('Someone requested %.', request);
    next();
  }
  render(){
    return <a/>
  }
}
//Note that even though the middleware element isn't rendered, React
//still requires components to have render methods that return components

app.get('*', jsXpress(
    <jsXpress.NoRender>
      <LoggerMiddleWare />
      <WelcomePage renderat= '/' prerender={preRenderer}/>
      <SignInPage renderat='signin' />
      <jsXpress.NoRender renderthrough="about">
        <AboutPage renderat='/' ></AboutPage>
        <AboutPage renderat='/team' text='Who we are... '></AboutPage>
        <AboutPage renderat='/whatwedo' text='What we do...'></AboutPage>
        <AboutPage renderat=':name' prerender={nameRenderer}></AboutPage>
      </jsXpress.NoRender>
    </jsXpress.NoRender>,
    {routeParams:true}
);

jsXpress features a convenience method for turning existing middleware into React Components

var morgan = require('morgan');
var MorganLogger = jsXpress.middlewareComponent(morgan);

app.post('*', jsXpress(
    <jsXpress.NoRender>
      <MorganLogger/>
      <WelcomePage renderat= '/' prerender={preRenderer}/>
      <SignInPage renderat='signin' />
      <jsXpress.NoRender renderthrough="about">
        <AboutPage renderat='/' ></AboutPage>
        <AboutPage renderat='/team' text='Who we are... '></AboutPage>
        <AboutPage renderat='/whatwedo' text='What we do...'></AboutPage>
        <AboutPage renderat=':name' prerender={nameRenderer}></AboutPage>
      </jsXpress.NoRender>
    </jsXpress.NoRender>,
    {
      routeParams : true,
      renderThenable : true
    }
);

##Asynchronicity If you do not wish to respond immediately, the prerender function can return a theanable to be fulfilled with a renderable component later. Set the renderThennable option to true to enable this.

var nameRenderer = function(element, request){
  return new Promise(){
    setTimeout(function(){
      fulfill(React.cloneElement(
        element,
        {text : "Your name is " + request.routeParams.name}} + ".");)
    },
    1000)
  };
}

app.post('*', jsXpress(
    <jsXpress.NoRender>
      <MorganLogger/>
      <WelcomePage renderat= '/' prerender={preRenderer}/>
      <SignInPage renderat='signin' />
      <jsXpress.NoRender renderthrough="about">
        <AboutPage renderat='/' ></AboutPage>
        <AboutPage renderat='/team' text='Who we are... '></AboutPage>
        <AboutPage renderat='/whatwedo' text='What we do...'></AboutPage>
        <AboutPage renderat=':name' prerender={nameRenderer}></AboutPage>
      </jsXpress.NoRender>
    </jsXpress.NoRender>,
    {
      routeParams : true,
      renderThenable : true
    }
);

##Dynamic vs Static If you're rendering html for dymanic sites that will use react on the front end, you can render them with react-binding for better startup time. You do this by setting the dynamic option to true.

app.post('*', jsXpress(
    <jsXpress.NoRender>
      <MorganLogger/>
      <WelcomePage renderat= '/' prerender={preRenderer}/>
      <SignInPage renderat='signin' />
      <jsXpress.NoRender renderthrough="about">
        <AboutPage renderat='/' ></AboutPage>
        <AboutPage renderat='/team' text='Who we are... '></AboutPage>
        <AboutPage renderat='/whatwedo' text='What we do...'></AboutPage>
        <AboutPage renderat=':name' prerender={nameRenderer}></AboutPage>
      </jsXpress.NoRender>
    </jsXpress.NoRender>,
    {
      routeParams : true,
      renderThenable : true,
      dynamic:true
    }
);

##Todo Decouple JSX from React Clarify differences between components and elements

##Known Issues

I think there is a bug with using the renderthrough

Right now, there seem to be some issues with using other middleware after jsXprss

#Appendix

##Full Application

var React = require('React');
var app = require('express')();
var jsXpress = require('jsxpress');
var morgan = require('morgan');
var MorganLogger = jsXpress.middlewareComponent(morgan);

var nameRenderer = function(element, request){
  return new Promise(){
    setTimeout(function(){
      fulfill(React.cloneElement(
        element,
        {text : "Your name is " + request.routeParams.name}} + ".");)
    },
    1000)
  };
}

var preRenderer = function(element, request, response){
  return React.cloneElement(element, {message:"Hello Universe!"});
}
class WelcomePage extends React.Component{
  constructor(props){
    this.state = {
      messate : props.message || "Hello World"
    }
  }
  render(){
    <html renderat='/signin'>
      <body>
        {this.state.message}
      </body>
    </html>
  }
}
class SignInPage extends React.Component{
  constructor(){
  }
  render(){
    <html renderat='/signin'>
      <body>
        Sign In
      </body>
    </html>
  }
}
class AboutPage extends React.Component{
  constructor(props){
    this.state = {
      text : props.text || "Lear About Us"
    }
  }
  render(){
    <html renderat='/signin'>
      <body>
        {this.state.message}
      </body>
    </html>
  }
}

app.post('*', jsXpress(
    <jsXpress.NoRender>
      <MorganLogger/>
      <WelcomePage renderat= '/' prerender={preRenderer}/>
      <SignInPage renderat='signin' />
      <jsXpress.NoRender renderthrough="about">
        <AboutPage renderat='/' ></AboutPage>
        <AboutPage renderat='/team' text='Who we are... '></AboutPage>
        <AboutPage renderat='/whatwedo' text='What we do...'></AboutPage>
        <AboutPage renderat=':name' prerender={nameRenderer}></AboutPage>
      </jsXpress.NoRender>
    </jsXpress.NoRender>,
    {
      routeParams : true,
      renderThenable : true,
      dynamic:true
    }
);
app.listen(8080);