Meteor server side rendering is about to become much easier

It might be time to update the title to “Meteor server side rendering has just become much easier”

I’m still trying to figure out how this works… hoping it works well with Blaze.

If anyone’s interested, I got started by updating my app, adding server-render, and then adding the following snippet to my app:

// inside of "/server/server-render.js"

import { onPageLoad } from "meteor/server-render";

onPageLoad(function (sink) {
  sink.appendToBody('greetings, world')
  console.log(sink)
});

It looks like you can choose what to render into the page by getting the URL out of the sink variable. Then, you just tell it what HTML to return - it looks like it can be anything.

Then, on the client, I suppose we can add a callback through Meteor.startup() to remove whatever we rendered in and render the real app in its place.

Off hand, it looks like a good way to put a placeholder or some initial screen while the rest of the bundle downloads. That’s the main use case I could see for now.

I wonder - is there a way to make sure this functionality runs synchronously, and to be able to block rest of the bundle from downloading? I think there could be a few benefits here:

  • we could serve entirely static websites as a backwards compatibility measure
  • if we detect a bot from Google, we can render a fresh page for it and deliver it as HTML
  • ban bad IPs from accessing the website

I also noticed the field request.url.auth - I thought it detects authentication but it has not worked so for me. It would be nice though.

It would be tempting to build a router around this feature.

2 Likes

I’m using it on the Todos app. I did notice that the onPageLoad() callback runs every time the URL changes on an app. Probably something caused by Iron Router. Seems like it would carry an unnecessary performance cost. Does anyone else think it would be better if it only ran on that first request, since the app should run as a SPA past the initial load?

@benjamn I always get the following error message:

renderIntoElementById is not a function

I’m doing this:

import { renderIntoElementById } from 'meteor/server-render';

I agree that onPageLoad probably should not run more than once, though I would also note you’re not obligated to use onPageLoad on the client at all. Pull requests welcome!

The API changed between this forum post and the Meteor 1.5.1 release: https://github.com/meteor/meteor/blob/master/packages/server-render/README.md

1 Like

Indeed - I am more concerned about the server requests because they could add up on an active website.

I hate to sound spoiled here - I appreciate and enjoy this functionality - but is there a plan for more work on it?

Thanks @benjamn, this works like a charm :). Thank you for the great work. I’m just wondering if it is also possible to manipulate a special tag (currently, sink seems only to support appendTo and renderInto). In our case, we want to add the lang tag to the html tag on the top, so we need something like this:

<html lang="de"></html>

React-Helmet supports that, but I don’t know how to manipulate the generated tag on the server side.

1 Like

If I am hosting on Galaxy, are mdg:seo and server-render packages mutually exclusive? Meaning, use one or use the other, but do not use both? seo attempts to use Prerender.io service, but I wonder if that’s even needed anymore for an app that uses server-render. Thoughts?

prerender.io removes the lift of server-side rendering from your server’s CPU since they cache the rendered page and serve that. if you use server-renderer it will use a bit more CPU to construct the rendered page. I suppose it would depend on your specific app which one is right for you

But you can also cache the HTML string and serve it via your app, so it isn’t a real problem. The easiest solution is to use https://www.npmjs.com/package/node-cache

3 Likes

Fantastic addition to Meteor. After significantly decreasing my load times with 1.5 this is another great way to improve the initial user experience.

Is there any way to access the request headers for server rendering?

I’m passing the request url to a StaticRouter and rendering my app with ReactRouter just fine but the Material UI package wants the user-agent to render on the server. I could maybe use sink.request.browser to construct myself but hopefully there’s a more direct way.

1 Like

Awesome, much needed addition to Meteor. This will significantly improve user experience. Any idea on how one might use server-render with react-router ?

It looks like they are unrelated. The easiest way I think to explain server-render is to say that it lets you inject some initial HTML into your page while your app loads.

Usually, when your app loads, the screen is blank as the JS and CSS are loaded, and then the JS would render in the HTML. This package basically lets you put some HTML in place ahead of that.

It looks like the package could be developed up to have a router and other things, which could be nice for serving data to search engines and etc. However, the HTML could be rendered in asynchronously, if for example it’s waiting on data from an external source, so I think one would still need a service like prerender.io.


The best use case I see for this is to display loading screens for your app. It would be great to hear how others are using it.

3 Likes

You mean for the official server-render package? If you are on React, you can send the whole rendered page to the user on initial load. That’s a big difference. There is normally no need anymore for a loading indicator. We are using it on https://www.muzica.io . You can check the HTML source code there. The whole page is available on initial load.

Oh that sounds cool. I guess after the client js initializes, React will take over the page and start updating it automatically?

Yep. You can see it when you use the german language. On initial load the main page is in english, after React has initialized the user gets redirected to the german one. But if the user surfs straight to https://www.muzica.io/de he will also the german one on initial page load (which is good for SEO if you use language tags, because Google will show automatically this version to german users).

Would a good use of Meteor new SSR abilities be Server-Side HTML emails?

In case anyone was wondering, I tried a test deploy to Galaxy with msg:seo and server-render packages both installed. What happened is Galaxy detects mdg:seo and causes it to take precedence. What I mean by this is if you’re trying to use server-render for seo meta purposes, it won’t work with mdg:seo installed because crawlers / sharers like Facebook are instructed to fetch from prerender rather than directly from your HTML head. After removing mdg:seo I got the results I wanted, and best of all, no more dealing with long cache busting delays with the prerender service.

2 Likes

By prerender service you mean prerender.io?

1 Like