UNPKG

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