node package manager

nuclear-sailboat

Nuclear Sailboat @0.2.0

A comprehensive React middleware and client reconciliation library for Sails.js


This library is under active, pre-alpha development and the documentation provided herein may not be accurate.


Features

  • Isomorphic components - rendered on the server, reconciled on the client (✝)
  • Lazy-loading and per-page caching of components (✝)
  • No additional client dependencies besides React/ReactDOM
  • Highly configurable

✝ may be disabled with configuration

Installation

Due to the nature of how Nuclear Sailboat must be integrated into a Sails project, it is not feasible at this time to offer an automated way to do these things. Each step of the installation offers some kind of configuration which should not be consolidated. In the future, Sails may have some sort of addon system that would be suitable.

Note that if you would like to use JSX syntax, that should be set up separately as it is not part of the package's core functionality. For a guide on doing this (in a way that is compatible with this package), please see Guide: Using JSX via Babel in the Asset Pipeline.

1. Install the package

Install via npm:

npm install nuclear-sailboat

Add it to your project's package.json:

// package.json
{
    ...,
    "dependencies": {
        ...,
        "nuclear-sailboat": "latest"
    }
}

2. Configure the middleware

In your project's config/http.js file, add the following middleware declaration:

// config/http.js 
module.exports.http = {
    ...,
    middleware: {
        ...,
        react: require('nuclear-sailboat').middleware(require('path').join(__dirname, '..')),
        ...,
        order: [
            ...,
            'react',
            ...
        ]
    }
};

The reason that the project root directory is passed as an argument is so that components can be found in their default location.

This loads the middleware with the default settings, which should be good enough for most use cases. If you would like to granularly override the configuration, use .configuredMiddleware({ ... }) insyead of .middleware. For detailed information on what configuration options are available, see Guide: Configuration.

The order in which the middleware is called is not very important, but err towards putting it earlier rather than later.

3. Add client dependency

In order to reconcile components on the client after a page is loaded, React must be accessible from the window object. There are many ways to do this. The simplest way to do this is to put react.min.js in assets/js/dependencies and put a script tag in layout/index.ejs so that it is available on all pages.

Usage

Defining components

By default, components are defined in the assets/js/components/ folder. The way that you define components is agnostic of the framework - the only requirement is that calling require('assets/js/components/YourComponentName') be able to find it - either in .../YourComponentName.js or .../YourComponentName/index.js or some other main entry point as specified by a package.json. If you can't conform to this requirement or need to do something more complicated, see Guide: Overriding Finding Components.

Due to the isomorphic nature of Nuclear Sailboat, some restrictions apply to how the components themselves can work. For components that are rendered on the server, in methods invoked before the component is mounted, they:

  • cannot reference client-only global variables such as document and window
  • cannot reference server-only variables such as require (unless using something like Browserify, which is recommended for better compatibility), global, and module
  • cannot use client-only APIs and libraries such as the DOM and jQuery
  • reflect in the initial rendered result any inconsistent state (i.e. cause the server's result to be different than what the client expects)

Embedding components

To embed a component in a page, call the component function in an EJS file:

<h1>Hello world, I'm a regular heading!</h1>
<%- component('TestComponent`, { someProperty: "This is pretty cool, right?" }) %>

Note that because it is embedding content on the page from a string, the raw <%- embed tag is required. React sanitizes the resulting markup already - I assure you that I don't take raw content injection lightly and that this is safe.

This does two things:

  • renders the component on the server and embeds this result on the page
  • embeds a small script that mounts the component on the page with the same properties and children once it's loaded

As a result of the client reconciliation, properties passed to the component must be serializable as JSON. It is possible to disable client reconciliation and thus remove this limitation. Additionally, you can specify serialization and deserialization functions to communicate rich properties from the server to the client.