Name: node-horse
Owner: Reddit
Description: null
Created: 2015-02-26 19:18:44.0
Updated: 2018-04-28 22:09:45.0
Pushed: 2016-04-19 18:52:44.0
Homepage: null
Size: 184
Language: JavaScript
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
horse is a couple of helper classes that can be used to help you build isomorphic applications for io.js / node. It abstracts routing and rendering helpers so that you can plug in a rendering system, bind links, and have an application that works anywhere.
The vast bulk of your application will live in your routes file (routes.jsx
in the example below), your API library, and your views - and will be shared
between the server and the client. horse's job is to get out of the way so that
you don't care where the code is running, and yet you get both server-side and
client-side rendering.
===================================
Your App
-------+ +---------------+
koa | | html5 history |
-------+ | api |
| +---------------+
eq req
| | render and
\ / wait for new route
------------------------ event
| ^
v |
=================================== |
+--------------+ |
| horse/App.js | |
+--------------+ |
| |
v |
================================= |
Your App's Routes |
|
+---------------+ |
| route handler | -> yield { body: reactElement }
| | -> throw MissingAuthenticationError();
+---------------+
The App has an instance of an Express-like request router that it uses to map requests to the appropriate handling function, and is run on both the client- and server- side. It's meant to abstract just enough boilerplate out of the way so that you can do your own custom stuff.
An example usage might be like: (es6 incoming)
routes.jsx
his is used both client- and server- side, and simply sets up an app with
outes; in this case, returning React elements.
rt Layout from '../layouts/layout.jsx';
rt Index from '../pages/index.jsx';
tion setupRoutes(app) {
p.router.get('/', function *() {
this.layout = Layout;
var user = yield db.getUser(1);
this.props = { user };
this.body = <Index {...this.props} />;
;
rt default setupRoutes;
server.es6.js
rt koa from 'koa';
rt React from 'react';
rt {App} from 'horse';
rt setupRoutes from './setupRoutes';
server = koa();
app = new App();
pRoutes(app);
er.use(function *(next) {
eld app.route(this, function () {
var Layout = this.layout;
this.body = react.renderToStaticMarkup(
<Layout>{this.body}</Layout>
);
;
client.es6.js
rt React from 'react';
rt {ClientApp} from 'horse';
rt setupRoutes from './setupRoutes';
rt jQuery as $ from 'jquery';
app = new ClientApp();
pRoutes(app);
$mountPoint = document.getElementById('app-container');
nction() {
'body').on('click', 'a', function(e) {
var $link = $(this);
var ctx = app.buildContext($link.attr('href'));
yield app.route(ctx);
React.render(ctx.body, $mountPoint);
;
Default events:
on('route:start', function(ctx){})
on('route:end', function(ctx){})
on('route:end', function(error, ctx, app){})
You can also add an array of request start / end functions that operate per request, instead of globally on the app:
startRequest.push(function(app, server) {
(server) { console.log('started on the server'); }
endRequest.push(function(app, server) {
(server) { console.log('started on the server'); }
ignore npm
and add .es6.js
to the transpiled files, like
so:ire('babel/register')({
nore: false,
ly: /.+(?:(?:\.es6\.js)|(?:.jsx))$/,
tensions: ['.js', '.es6.js', '.jsx' ],
urceMap: true,