UNPKG

3.67 kBMarkdownView Raw
1horse
2=====
3
4horse is a couple of helper classes that can be used to help you build isomorphic
5applications for io.js / node. It abstracts routing and rendering helpers so
6that you can plug in a rendering system, bind links, and have an application
7that works anywhere.
8
9A Brief Overview
10----------------
11
12```
13 ======================================
14 Your App
15
16 +---------+ +---------------+
17 | koa | | html5 history |
18 +---------+ | api |
19 | +---------------+
20 req req
21 | | render and
22 \ / wait for new route
23 ------------------------ event
24 | ^
25 v |
26 ====================================== |
27 +--------------+ |
28 | horse/App.js | |
29 +--------------+ |
30 | |
31 v |
32 ==================================== |
33 Your App's Routes |
34 |
35 +---------------+ |
36 | route handler | -> yield { body: reactElement }
37 | | -> throw MissingAuthenticationError();
38 +---------------+
39```
40
41The App has an instance of an Express-like request router that it uses to map
42requests to the appropriate handling function, and is run on both the client-
43and server- side. It's meant to abstract just enough boilerplate out of the
44way so that you can do your own custom stuff.
45
46An example usage might be like: (es6 incoming)
47
48`routes.jsx`
49
50```javascript
51// This is used both client- and server- side, and simply sets up an app with
52// routes; in this case, returning React elements.
53
54import Layout from '../layouts/layout.jsx';
55import Index from '../pages/index.jsx';
56
57function setupRoutes(app) {
58 app.router.get('/', function *() {
59 this.layout = Layout;
60
61 var user = yield db.getUser(1);
62 this.props = { user };
63
64 this.body = <Index {...this.props} />;
65 });
66}
67
68export default setupRoutes;
69```
70
71
72`server.es6.js`
73
74```javascript
75import koa from 'koa';
76import React from 'react';
77
78import {App} from 'horse';
79import setupRoutes from './setupRoutes';
80
81var server = koa();
82
83var app = new App();
84setupRoutes(app);
85
86server.use(function *(next) {
87 yield app.route(this, function () {
88 var Layout = this.layout;
89
90 this.body = react.renderToStaticMarkup(
91 <Layout>{this.body}</Layout>
92 );
93 });
94}
95```
96
97`client.es6.js`
98
99You'll want to add push state too, but that's outside the scope of our
100example.
101
102```javascript
103import React from 'react';
104import {ClientApp} from 'horse';
105
106import setupRoutes from './setupRoutes';
107
108import jQuery as $ from 'jquery';
109
110var app = new ClientApp();
111setupRoutes(app);
112
113var $mountPoint = document.getElementById('app-container');
114
115$(function() {
116 $('body').on('click', 'a', function(e) {
117 var $link = $(this);
118
119 var ctx = app.buildContext($link.attr('href'));
120 yield app.route(ctx);
121
122 React.render(ctx.body, $mountPoint);
123 });
124});
125
126```
127
128
129Final Notes
130-----------
131
132* This is all ES6, so you'll want to use a transpiler; I like
133[babel](http://babeljs.io). To get babel to work with npm modules, you'll
134need to turn off `ignore npm` and add `.es6.js` to the transpiled files, like
135so:
136```
137require('babel/register')({
138 ignore: false,
139 only: /.+(?:(?:\.es6\.js)|(?:.jsx))$/,
140 extensions: ['.js', '.es6.js', '.jsx' ],
141 sourceMap: true,
142});
143```
144* Tested with iojs 1.0.0 and later and node 0.10.30 and later.