├── .gitignore
├── .jshintrc
├── README.md
├── index.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | node_modules/
3 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "asi": false,
3 | "bitwise": true,
4 | "browser": false,
5 | "curly": false,
6 | "eqeqeq": true,
7 | "eqnull": true,
8 | "esnext": false,
9 | "immed": true,
10 | "latedef": false,
11 | "newcap": false,
12 | "noarg": true,
13 | "nonew": true,
14 | "quotmark": false,
15 | "undef": true,
16 | "unused": "vars",
17 | "globalstrict": true,
18 | "trailing": false,
19 | "validthis": true,
20 | "loopfunc": true,
21 | "expr": true,
22 | "globals": {
23 | "Buffer": true,
24 | "define": true,
25 | "module": true,
26 | "require": true,
27 | "exports": true,
28 | "describe": true,
29 | "xdescribe": true,
30 | "beforeEach": true,
31 | "afterEach": true,
32 | "it": true,
33 | "xit": true,
34 | "escape": true,
35 | "process": true,
36 | "__dirname": true
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # express-react-engine
2 |
3 | This is an [Express](http://expressjs.com) view engine for [React's](http://http://facebook.github.io/react/) JSX that supports server side rendering and **it is not limited to static markdown**.
4 |
5 | ## Usage
6 |
7 | ```
8 | npm install express-react-engine react react-dom
9 | ```
10 |
11 | Make sure you install `react` and `react-dom` as dependencies.
12 |
13 |
14 | ### Add it to your Express App
15 |
16 | ```javascript
17 | var ReactEngine = require('express-react-engine');
18 | var app = express();
19 |
20 | app.set('views', __dirname + '/components');
21 | app.engine('jsx', ReactEngine());
22 | ```
23 |
24 | Change your *views directory* to match your *components directory* and set `jsx` as your view engine.
25 |
26 |
27 | ## Options
28 |
29 | `wrapper` is a React component that renders the Html element as well as the initial props and children Html.
30 |
31 | ### Example
32 |
33 | ``` javascript
34 | app.engine('jsx', reactEngine({wrapper: 'html.jsx'}));
35 | ```
36 |
37 | **/components/html.jsx**
38 | ``` javascript
39 | var React = require('react');
40 |
41 | var Html = React.createClass({
42 | render: function () {
43 | return (
44 |
45 |
46 | {this.props.props.title}
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | );
56 | }
57 | });
58 |
59 | module.exports = Html;
60 |
61 | ```
62 |
63 | ## Views
64 |
65 | Your `views` can be simple modules that export a React Component.
66 |
67 | ```javascript
68 | var React = require('react');
69 |
70 | var Home = React.createClass({
71 | render: function () {
72 | return (
73 |
74 | E.T. Phone Home!
75 |
76 | );
77 | }
78 | });
79 |
80 | module.exports = Home;
81 | ```
82 |
83 | ## Routes
84 |
85 | You can use your `routes` the same way you always did in **Express**. Just render the React component instead of a jade/hjs/hbs template. Passing an object to the component as `props` is also straightforward, just add it as the second argument of `res.render()`.
86 |
87 | ```javascript
88 | var express = require('express');
89 | var router = express.Router();
90 |
91 | router.get('/', function (req, res, next) {
92 | res.render('home/index.jsx', { foo: 'bar' });
93 | });
94 |
95 | module.exports = router;
96 |
97 | ```
98 | Now `foo` will be available within the component as `this.props.foo`.
99 |
100 | ## Layouts
101 |
102 | Obviously you can still use Layouts if you want. Just create a component that will render the "layout stuff" and pass him via props the component that you want to be laid out :)
103 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react');
4 | var ReactDOMServer = require('react-dom/server');
5 | var defaults = require('lodash.defaults');
6 | var path = require('path');
7 |
8 | module.exports = function engineFactory (engineOptions) {
9 | engineOptions = defaults(engineOptions || {}, {
10 | extension: '.jsx',
11 | babel: {},
12 | docType: '',
13 | staticMarkup: false
14 | });
15 |
16 | if (engineOptions.babel) {
17 | require('babel-core/register')(engineOptions.babel);
18 | }
19 |
20 | function requireComponent(_path_){
21 | return require(_path_) ? require(_path_).default ? require(_path_).default : require(_path_) : require(_path_);
22 | }
23 |
24 | return function renderComponent (filename, options, callback) {
25 | options = options || {};
26 |
27 | try {
28 | var markup = engineOptions.docType;
29 | /**
30 | Depending on whether one is using ES6 import/export style modules,
31 | or Node's require/exports style Modules, we need to specify how
32 | we should reference the component from the required file
33 | */
34 | var ReactComponent = requireComponent(filename);
35 | var instance = React.createElement( ReactComponent, options);
36 |
37 | var componentMarkup;
38 |
39 | if (engineOptions.staticMarkup) {
40 | componentMarkup = ReactDOMServer.renderToStaticMarkup(instance);
41 | } else {
42 | componentMarkup = ReactDOMServer.renderToString(instance);
43 | }
44 |
45 | if (engineOptions.wrapper) {
46 | var Wrapper = requireComponent(path.join(this.root, engineOptions.wrapper));
47 | var wrapperInstance = React.createElement(Wrapper, {
48 | body: componentMarkup,
49 | props: options
50 | });
51 |
52 | markup += ReactDOMServer.renderToStaticMarkup(wrapperInstance);
53 |
54 | } else {
55 | markup += componentMarkup;
56 | }
57 |
58 | if (options.settings.env === 'development') {
59 | Object.keys(require.cache).forEach(function(module) {
60 | if (new RegExp('\\' + engineOptions.extension + '$')
61 | .test(require.cache[module].filename)) {
62 | delete require.cache[module];
63 | }
64 | });
65 | }
66 |
67 | callback(null, markup);
68 | } catch (error) {
69 | callback(error);
70 | }
71 | };
72 | };
73 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "express-react-engine",
3 | "version": "1.0.0",
4 | "description": "A React's JSX rendering engine",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/magalhas/express-react-engine.git"
12 | },
13 | "author": "José Magalhães ",
14 | "license": "ISC",
15 | "bugs": {
16 | "url": "https://github.com/magalhas/express-react-engine/issues"
17 | },
18 | "homepage": "https://github.com/magalhas/express-react-engine",
19 | "peerDependencies": {
20 | "react": "^0.14.0 || ^15.0.0",
21 | "react-dom": "^0.14.0 || ^15.0.0"
22 | },
23 | "dependencies": {
24 | "babel-core": "^6.0.0",
25 | "lodash.defaults": "^3.1.0"
26 | },
27 | "devDependencies": {
28 | "react": "^15.0",
29 | "react-dom": "^15.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------