Meteor - Server Side Rendering

meteor

https://github.com/meteorhacks/meteor-ssr/ - done reading
https://themeteorchef.com/tutorials/using-the-email-package
https://meteorhacks.com/meteor-server-sider-rendering-for-seo-purpose/ - done reading
https://meteorhacks.com/server-side-rendering/ - done reading
https://disqus.com/home/discussion/meteorhacks/meteor_server_side_rendering_for_seo_purposes/
https://crater.io/posts/ybJX6k4X2bApPomqG/server-side-rendering-for-seo-purposes
http://tomdale.net/2015/02/youre-missing-the-point-of-server-side-rendered-javascript-apps/
https://themeteorchef.com/tutorials/server-side-routing-with-picker
https://news.ycombinator.com/item?id=10937286

How can we combine server side rendering and server side routing?

With meteor, the term server side rendering does not necessarily coincide with the term server side routing. For example, if we instead of wanting to get the data from the server, we want the server to get the data and evaluate the template (merge that data into a template), and return just the result, that is an example of server side rendering. To accomplish this kind of server side rendering, the client side issue a call, using the .call method. If we want a page to be rendered on the server side, we can use FastRender, or we can use meteorhacks:picker, a server-side routing module. First, create the template inside the private folder:

{{{getDocType}}}
<html lang="en">
  <head>
    <style type="text/css">
    {{css}}
    </style>
  </head>
  <body>
    <div id='server_side'>
      This is a test
    </div>
  </body>
</html>

The above code is in private/browse.html.

And then, inside our server/main.js:

Meteor.startup(() => {
  // code to run on server at startup
  if (Meteor.isDevelopment) {
    DeckCategories.remove({});
    DeckCategories.insert({categories: ['Technology','Science','Language','Math','Financial']});
  }
  SSR.compileTemplate('browse', Assets.getText('browse.html'));
  Template.browse.helpers({
    getDocType: function() {
      return "<!DOCTYPE html>";
    }
  });
});

Notice that we uses Assets.getText to get the template from the private folder, invokes SSR.compileTemplate to compile it and give it a name 'browse'. Unlike the normal template, this template does not start with the @template name="..."@ construct. After we compile the template, we define the helpers. Blaze does not allow us to render a template that contains a DOCTYPE, so we define the helper getDocType, and use it inside the template.

So far, we only discussed about server side rendering. To combine server side rendering with server side routing, add the meteorhacks:picker module:

meteor add meteorhacks:picker

and then create the lib/routes.js:

var css = Assets.getText('style.css');
var seoPicker = Picker.filter(function(req,res) {
  //return /_escape_fragment_/.test(req.url);
  return true;
});
seoPicker.route('/browse', function(params, req, res) {
  var html = SSR.render('browse', {
    css: css,
    template: "browse",
    data: {}
  });
  res.end(html);
});

When the browser (or any HTTP client) request the /browse from the server, our function gets invoked, and at this point, we can fetch the data from the database, and pass it onto the SSR.render call when the data is ready. Perhaps we can accomplish this by creating a promise, or using a callback (preferably we should be using promise).

How can we do server side rendering?

meteor add meteorhacks:ssr

First create templates and helpers:

SSR.compileTemplate('emailText', 'Hello {{username}}, <br> Now time is: {{time}}');

Template.emailText.helpers({
  time: function() {
    return new Date().toString();
  }
});

Then you can render above template anywhere in your app.(only on server):

Meteor.methods({
  sendEmail: function() {
    var html = SSR.render("emailText", {username: "arunoda"});
    console.log(html);
  }
});

It's not a good idea to write template(html) inside javascript. So, we can use following approach. Write your html content inside the private directory:

<!-- file: private/hello.html -->
Hello {{username}}, <br>
Now time is: {{time}}

Then load it like this:

SSR.compileTemplate('emailText', Assets.getText('hello.html'));

Template.emailText.helpers({
  time: function() {
    return new Date().toString();
  }
});

How can we use the SSR.render(template, data) method?

SSR.render(template, data)

You can render a template with data. For template argument you can either pass the name of the template or the actual template instance itself.

How can we use the SSR.compileTemplate(templateName, stringTemplateContent, [options]) method?

SSR.compileTemplate(templateName, stringTemplateContent, [options])

You can use this API to compile templates in the server. The options parameter allows you to choose the template language with the language option. If not provided this default to html which is handled by the spacebars compiler. You can also use jade as another option — and in this case you need to add following package:

meteor add mquandalle:jade

Note: the order in which you add jade and SSR matters! First add jade as a dependency and then SSR, otherwise the jade-compiler can not be located by Meteor.

How can we use Jade with the meteorhacks:ssr package?

SSR.compileTemplate(templateName, stringTemplateContent, [options])

You can use this API to compile templates in the server. The options parameter allows you to choose the template language with the language option. If not provided this default to html which is handled by the spacebars compiler. You can also use jade as another option — and in this case you need to add following package:

meteor add mquandalle:jade

Note: the order in which you add jade and SSR matters! First add jade as a dependency and then SSR, otherwise the jade-compiler can not be located by Meteor.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License