I'm looking for the best technology/architecture choices for my isomorphic app. Here are my constraints, due to what has already been developed, what we need and what we'd love:
- All front-end in React.js, with layout(s), child components, etc.
- Flux architecture
- As I said, server-side rendering (the current server is built on express.js, it can change but if we can keep it it would save some time)
- Very simple/flexible router, like react-router or even just a json route:component, I don't know
- Each component should be able to ask for the data it needs before render
- Each component should be able to have a specific context (set page title, insert specific css, set meta tags, etc.)
To be clear, we need to be able to add a page/feature on the app by simply saying in the router file "This route needs to render this component, inside this layout" and the component should be independent, asking "ok, before everything, I need these data from the api, then, I need this css file, my title is 'title', ect.".
The architecture we currently have is a mess, not maintainable, not scalable, not flexible enough:
With and Express.js router, on each route we set context information, make an api call and then render a jade file with specific css and js, in which we insert the jsx component. Here is an exemple:
router.js
router.get('/profile', function(req, res, next) {
// make the api call
api.getProfile(function(err, profile) {
if (err) {
next(err);
}
// set props for the react component
var props = {
profile: profile
};
// render the react component
var ProfileEditor = React.createFactory(
require('path/to/components/profile.jsx')
);
var profileEditor = React.renderToString(
ProfileEditor(props)
);
// render the jade file
res.render('profile', {
props: safeStringify(props),
profile:profileEditor
});
});
});
profile.jade
// extend a layout
extends ../layout
// ask for specific styles if need
block styles
// insert the server side rendered component
block component
#profile
!= profile
block scripts
// ask for specific scripts if needed
script(src="https://maps.googleapis.com/maps/api/js?key=key&libraries=places")
// print props for the client side rendering
script(id="props" type="application/json")
|!{ props }
// set the react component
script(src="/bundles/profile.js")
profile.jsx
var React = require("react");
var store = require ('../stores/profile');
var actions = require ('../actions/profile');
var Profile = React.createClass({
// As usual
render: function(){
return(
<div>
// Profile component
</div>
)
}
});
// re-render client side using the same props from the script tag
if (typeof window !== 'undefined') {
var ProfileFactory = React.createFactory(Profile);
var mountNode = document.getElementById("profile");
var props = JSON.parse(document.getElementById("props").innerHTML);
React.render(new ProfileFactory(props), mountNode);
}
module.exports = Profile;
Over the project grows, the less we are satisfied with that.
The solutions we've been trying to explore are :
yeoman generator react-fullstack: https://github.com/kriasoft/react-starter-kit/tree/yeoman-generator > we find it very complicated and we didn't managed how to simply fetch data for each component. Although it's exactly what we need about context for each component.
express.js + react-router: Client Routing (using react-router) and Server-Side Routing, http://putaindecode.fr/posts/js/reactjs-et-rendu-serverside/ > same problem with data, and we've not been able to set context. Also we are not so comfortable with the initial render server-side and then everything client side, at the opposite of what we currently have.
We feel like nothing is really adapted while we don't develop something really particular, just a platform to read/write data from an api.
What would be the best, simple, flexible, limpid architecture for us regarding our constraints? What choices do we need to do?