done-ssr

Server-side rendering for CanJS applications

Usage no npm install needed!

<script type="module">
  import doneSsr from 'https://cdn.skypack.dev/done-ssr';
</script>

README

Build Status npm version

done-ssr

Greenkeeper badge

Server-side rendering for DoneJS.

Install

npm install done-ssr --save

Usage

done-ssr takes a steal configuration object (the same object used by steal-tools to configure building) and returns a function that will render requests.

Pass your request into the render function and pipe the resulting stream into the response.

const http = require("http");
const ssr = require("done-ssr");
const render = ssr();

const server = http.createServer(function(request, response){
    render(request).pipe(response);
});

server.listen(8080);

Your app

done-ssr expect's your project's main to export a function that renders based on the request parameter. This will work with any module format supported by Steal.

const ViewModel = DefineMap.extend( { ... });

module.exports = function(request){
  var params = route.deparam(location.pathname);
  var viewModel = new ViewModel(params);

  // Do whatever is needed to render
};

The request parameter is the raw Node request object so you can do things like get request headers if needed.

Additionally the location object is set globally so you can use it like you would in a browser window.

More can be found in the main module docs.

Express Middleware and Development Server

done-ssr provides the low-level server rendering capabilities in DoneJS. It takes a request and a response and renders your application into the response. If you are writing a Node server yourself, done-ssr is likely for you.

If you are using a framework, like Express then you'll want to use done-ssr-middleware.

If you're looking for a development server that provides you most of what you need, and can run from the cli, then use done-serve.

API

ssr(steal, options) -> render

The ssr function contains two arguments, one for the steal object and one is an options object:

steal

Configuration options that are a StealConfig. This is the same object that is passed into steal-tools to configure the loader for building.

options

timeout : 5000

Specify a timeout in milliseconds for how long should be waited before returning whatever HTML has already been rendered. Defaults to 5000.

Debugging Timeouts

A timeout might occur for a variety of reasons such as:

  • Running in development: In development the server has to load all modules the first time a request is made. In this case the first render could timeout. You can specify a longer timeout to remedy this.
  • Unresolved promise: If you have a promise that never resolves it could cause a timeout. Be sure to always resolve your promises and catch rejections.
  • Undetectable recursion: can-zone tracks all types of asynchronous tasks. Some times it can't detect that a program will never complete. One example is setTimeout call that is called recursively. Use Zone.ignore to ignore those type of code.

If all else fails, use the debug option to get more information on why the timeout occurs.

debug : false

Specify to turn on debug mode when used in conjunction with timeout. If rendering times out debugging information will be attached to a modal window in the document. For this reason you only want to use the debug option during development.

debug output

exitOnTimeout : false

This option is for the rare instance where the above debugging tips and info do not resolve a timeout, or the timeout is sporadic and difficult to find. With this option set to true a timeout error will still display the warning, but will exit the Node process cleanly, allowing redundant processes to take over on future calls.

auth: {cookie, domains}

An object for enabling JavaScript Web Tokens (JWT) support for XHR requests made by the SSR server. Must contain both of the following values:

  • cookie: A string representing the cookie name where the SSR server can look to find a JWT token. That token gets applied as the "Bearer" token in the authorization header of every outgoing XHR.

For example, if the SSR server receives a cookie like feathers-jwt=<token>;, and the authCookie option is set to "feathers-jwt", outgoing requests from the SSR server will have an authorization header of Bearer <token>

  • domains: An array of domain names to which the JWT token will be sent. Any domains not in this list will not receive the JWT token.
strategy: 'incremental'

Specify the rendering strategy. Starting in done-ssr 3 the default is incremental. If you are using SSR primarily for SEO (and not performance) you will want to set this to seo.

const render = ssr(steal, {
  strategy: "seo"
});
zones

Specify additional zones to be added. This is an advanced option most will not need. You might add zones to do some sort of special processing to the DOM. You can essentially do whatever you want to data.document within a Zone like so:

const render = ssr({}, {
  zones: [
    function(data) {
      return {
        ended: function() {
          // Remove all scripts. Why, idk.
          let scripts = Array.from(data.document.getElementsByTagName("script"));
          for(let script of scripts) {
            script.parentNode.removeChild(script);
          }
        }
      }
    }
  ]
});
domZone

Specify the zone that provides the DOM. This zone must create a window, a document, and other associated globals and set them on Node's global.

This option is a function that takes the request and response. By default done-ssr uses can-simple-dom.

For example, this is how you can use can-zone-jsdom to get a much more complete DOM implementation.

const ssr = require('done-ssr');
const dom = require('can-zone-jsdom');

const render = ssr({}, {
  domZone: request => dom(request, {
    root: __dirname + '/build',
    html: 'index.html'
  })
});

// ... use render like normal.
xhrCache: true

Specifies if the XHR cache should be inlined into the page. The XHR cache is used to prevent duplicate requests from occuring in the client when hydrating from server-rendering HTML. In some cases you might not use XHR in the client and therefore want to prevent the script from being included.

const ssr = require('done-ssr');

const render = ssr({}, {
    xhrCache: false
});

render(request)

The render function is returned from the call to ssr and is what used to render requests. It returns a readable stream that can be piped into other streams, using the response stream.

render(request).pipe(response);

You can use request/response streams from servers created with require("http"), or Express and probably most other Node servers.

DONE_SSR_DEBUG

The DONE_SSR_DEBUG environment variable can be used if you need to debug what is happening during incremental rendering reattachment. This provides unminified reattachment code. Set it to any value to enable the debugging. export DONE_SSR_DEBUG=1.

License

MIT