react-server-render
This package can render ReactJS components on server side returning the script to initialize the component on client side and the resulting component html.
This task seems to be easy enough, so why a package?
1 - Avoid code all over the place!
2 - For developement environments the required modules are cached, so react components are modules too and this package prevents that from happening so that components modifications are up and running! This package only removes the cache from non-production envs.
3 - You will not need to add a placeholder html tag to set the destination of the component, the package does that for you!
Install package:
npm install react-server-render --save
Complete use case example:
React component (myComponent.jsx)
var React = require("react");
var ReactHandler = require("react-server-render");
// for this example i'll use a simple validation. You might need to check if window["varName"] isset too.
var initialState = ReactHandler.getInitialState("varName") !== null ?
ReactHandler.getInitialState("varName") : window["varName"];
// NOTE: Of course this initialState could be used to feed any Flux system, like Redux :)
var MyComponent = React.createClass({
getDefaultProps: function(){
return {
text: null
};
},
getInitialState: function(){
return initialState;
},
render: function(){
return (
<div>
{this.props.text}
</div>
);
}
});
module.exports = MyComponent;
Express router
...
var ReactHandler = require('react-server-render');
router.get('/', function(req, res, next) {
var ComponentParsed = ReactHandler.getComponent(
'components/myComponent',
{text: "Hello world"},
true,
{
componentId: "compId",
state: ["varName", {todos:["1", "2"], username: "danielmeneses"}]
}
);
res.render('index', {
componentHtml: ComponentParsed.html,
componentScript: ComponentParsed.script
});
});
...
EJS view (works with any view engine)
<!DOCTYPE html>
<html>
<head></head>
<body>
<header></header>
<main>
<%- componentHtml %>
</main>
<footer></footer>
<script src="/javascripts/react_components.js"></script>
<%- componentScript %>
</body>
</html>
Config VARS (optional)
// relative to node project root (default: "./build/reactjs/")
ReactHandler.PATH_TO_REACT_FILES = 'path_to_folder_where_files_are';
// js, jsx, ... (default: jsx)
ReactHandler.REACT_FILES_EXTENSION = 'files_extension';
// production, developement, ... (default: process.env.NODE_ENV)
ReactHandler.NODE_ENV = 'node_env';
About the getComponent() function:
/**
* Returns the component in two parts, intial script for client side and the component HTML
* @param {string} componentPath component path relative to ReactHandler.PATH_TO_REACT_FILES
* @param {object} componentProps object are passed as component props will overwritte props in getDefaultProps()
* @param {boolean} serverSideRender is the question: render this on server side or cliente side?
* @param {object} define component name and pass an object intentioned to be the initial state of the component
* @return {object} {html: '', script: ''}
*/
getComponent(componentPath, componentProps, serverSideRender)
Warning:
This package assumes that you expose the 'require' function on client side and the respective components script!
Each React component rendered on the server must be exposed and available using 'require' on client side and should only mention the relative path to the respective component, i.e., should be equal to the componentPath param of function getComponent(), something like: "component/myComponent". This can be achieved using a task manager like gulp, grunt or other adding expose attribute:
Changing module exposer name (expose module with a custom name)
var b = browserify();
b.require(pathToCompFile, {expose: "component/myComponent"});
// Be sure to expose "react" and "react-dom" packages to the browser. Like:
b.require("react", {expose: "react"});
b.require("react-dom", {expose: "react-dom"});