Rahul
Rahul

Reputation: 12231

Emulate server-side rendering with Meteor

As we all know, Meteor's initial payload sent to the client comprises (in production) a concatenated javascript file containing the Meteor platform, packages, and all templates parsed into Meteor's reactive templating system. Server-side rendering, where the templates are rendered to HTML and sent to the client in the initial payload, is on its way but doesn't have an expected release date yet.

I'm looking for a way to "hack" or approximate server-side rendering given the available functionality in Meteor 0.8.x. Specifically, I want to:

The use case is http://q42.com. I recognise Meteor isn't the best fit for static websites like this one but I want to try and see how far I can get anyway. Right now the Meteor platform JS file is over 600 KB in size (±200 KB gzipped) and I'd like to reduce this size if possible.

Note: I'm aware of and already using Arunoda's fast-render package, which is intended to send data with the initial payload. In this case I want to cut down on time-to-first-render by also getting the templates themselves down faster.

Upvotes: 2

Views: 1019

Answers (1)

Tarang
Tarang

Reputation: 75945

This is a little bit tricky. But there are some things you could do. This may not be the beeest way to do it but it could help you get started somehow.

Meteor is build with many packages as 'default', sometimes some are not needed. You can remove the standard-app-packages and add the packages (that you need and use manually) listed here: https://github.com/meteor/meteor/blob/devel/packages/standard-app-packages/package.js

To cut down the templates you would have to include the bare templates that you use and include the other template's separately and perhaps send down the Template information via a Collection, using a live observer handle to initiate the templates

You would have to 'render' the templates on the server side or store them manually in your collection using Spacebars.compile from the spacebars-compiler package which is a little tricky but you could have it done decently:

This should give you a rough idea, not sure how to get passed the 'eval' bit of it though:

HTML file in /private/template.html

<template name="test">
    Hello {{name}}
</template>

JS file in /private/template.js

Template.test.name = function() { return "Bob" }

Server side code

var collection = new Meteor.Collection("templates");

var templateData = Assets.getText("template.html");
var templateJs = Assets.getText("template.js");

var compiled = Spacebars.compile(templateData).toString();
var jsData = templateJs;

collection.insert({templateName:"test", data: templateData, js:  templateJs});

Client Side code

collection.find().observeChanges({
    added: function(id, fields) {
        var template = fields.data,
            name = fields.name,
            js = fields.js;

        Template["name"] = UI.Component.extend({
            kind: "name",
            render: eval(template),
        });

        eval(js);
    }
});

Then just subscribe to the collection asking for your template and it should exist. If you use iron-router I think (not sure) you could make the subscription wait before the template is rendered so you could have it work.

Again this is just a 'hacky' solution, one thing I personally don't like about it is the use of eval, but javascript needs to run somehow...

You could loop through files in a particular folder using fs = Npm.require('fs') to render each template too.

One alternative would be to inject a 'script' tag calling the compiled js template and template helpers to let the template exist.

Upvotes: 2

Related Questions