mystor / meteor-routecore

Client and server side rendering/routing powered by React
84 stars 6 forks source link

[Question] Server-side Blaze integration #9

Closed stringparser closed 10 years ago

stringparser commented 10 years ago

First, thanks for the awesome job. It works out of the box.

Would it be possible to use Blaze components with the RouteCore.BlazeComponent method? I've been thinking of using [this approach](http://www.meteorpedia.com/read/Blaze_Notes#How to render a template to HTML with data) to render templates server side, but RouteCore.BlazeComponent expects a compiled version of the template right?

mystor commented 10 years ago

RouteCore.BlazeComponent currently runs on both the client, and the server. That being said, on the server it currently just renders a <span>, and then the span is filled in on the client side, in a reactive manner.

The biggest reason for this, is that in order to render components - whether with RouteCore.BlazeComponent or any other Blaze method, the component has to first be compiled to JavaScript. Unfortunately, the .html file handler in Meteor's code currently opts to not compile the code to run on the server side - as it is not officially supported to use it as such. Thus, I don't necessarily know how to render a given component on the server side, as it is only visible to code on the client side.

However, if you did manage to get your template to be visible on the server side, you would also have to make some modifications to the BlazeComponent source. Namely, you would have to remove some Meteor.isClient checks - move some code from componentDidMount to componentWillMount, and probably render the HTML into a dangerouslySetInnerHTML in the render method (only on the server, of course). The changes shouldn't be too hard to do, but I'm not sure what problems you might run to in the process.

tl;dr: Yes and No, You can use BlazeComponent to render blaze components. However, RouteCore won't render anything on the server, only on the client. This is because Blaze's render methods require compiled Blaze templates to work, and BlazeComponent doesn't perform server side rendering.

stringparser commented 10 years ago

Haha, I did read all, and was kind of what I had in mind about this. Thanks for the fast response.

I'll investigate a bit further and let you know. Thus far I know there is a Spacebars.compile method on the server. Lets see what the afternoon gives.

stringparser commented 10 years ago

Ok, I got some movement although I can't see the component on the page.

I found a comment David Glasser left on meteor-talk on how they make the first page render (boilerplate.html mentioned there). Following that, this is what I've done (of course all server-side).

var tmpl = '<body>{{> hello}}</body>'
   tmpl += '<template name="hello"><h1>Hello React from Spacebars!</h1></template>';
tmpl = {
  type : typeof tmpl,
  value : tmpl,
  parsed : Spacebars.parse(tmpl),
  compiled : Spacebars.compile(tmpl)
};

tmpl.BlazeComponent = UI.Component.extend({
  kind : 'hello',
  render : new Function(' return ' + tmpl.compiled)()
})
tmpl.ReactComponent = RouteCore.BlazeComponent(tmpl.BlazeComponent)

// And the route
RouteCore.map(function(){
  this.route('/hello', tmpl.ReactComponent)
})

All variants on how the initial html string has to be written have not work (taking out the first line, etc). I've removed the Meteor.isClient from the BlazeComponent but even then UI needs dom at the end so.... I have also found a UI.toRawText(component) on [MeteorPedia](http://www.meteorpedia.com/read/Blaze_Notes#Helpers that can be called both regularly and as block helpers) but still doesn't help.

The only thought I have for this to work is use the react tools to parse an html string, eval it, since we are on the server and put in on this.props.ReactComponent when the component is created. But that's way to many pluming and makes no real sense :D. Plus after that, to make it work, React.renderComponentToString(component) would have to be used.

Anyway, I just needed some time in between I change the templates because I'm switching to React I find it more pleasant.