使用Meteor和Meteorhacks进行服务器端渲染:ssr和iron-router

时间:2014-10-12 07:16:02

标签: meteor

最近出现了https://meteorhacks.com/server-side-rendering.html,但似乎并不是一个如何使用铁路由器的完整示例。

如果我有一个模板,如: /private/post_page.html

{{title}}
{{#markdown}} {{body}} {{/markdown}}

如何使用特定ID请求中的单个记录属性填充它?

请求的页面是localhost:3000/p/:idofposthere如何用数据填充它并在铁路由器中为该路由/服务器端渲染它?

2 个答案:

答案 0 :(得分:5)

实际上比你想象的要容易一点(我只是按照Arunoda的SSR示例并将其转换为iron-router给你):

if(Meteor.isServer) {
  Template.posts.getPosts = function(category) {
    return Posts.find({category: category}, {limit: 20});
  }
}

Router.map(function() {
  this.route('home');
  this.route('view_post', {
    path: 'post/:id',
    where:"server",    
    action : function() {

      var html = SSR.render('posts', {category: 'meteor'})
      var response = this.response;

      response.writeHead(200, {'Content-Type':'text/html'});
      response.end(html);
    } 
  });
});

如果您为客户端和服务器端共享相同的路由,例如,如果您希望它基于用户代理呈现客户端,那么它变得棘手。

来源:我们在自己的应用上使用此策略。

更新

虽然上面的代码只是问题所要求的,但我们可以通过在到达客户端之前检查?_escaped_fragment_=查询字符串来遵循Google的Ajax规范。

基本上,我们对Iron-Router大多不了解的是,如果您为服务器和客户端声明了相同的路由,则先调度服务器端路由,然后再调度客户端路由。

这是主要的javascript(带注释):

ssr_test.js

Router.configure({
  layout: 'default'
});

Posts = new Mongo.Collection('posts');

// Just a test helper to verify if we area actually rendering from client or server.
UI.registerHelper('is_server', function(){
  return Meteor.isServer ? 'from server' : 'from client';
});

myRouter = null;

if(Meteor.isServer) {

  // watch out for common robot user-agent headers.. you can add more here.
  // taken from MDG's spiderable package.

  var userAgentRegExps = [
    /^facebookexternalhit/i, 
    /^linkedinbot/i, 
    /^twitterbot/i
  ];

  // Wire up the data context manually since we can't use data option 
  //   in server side routes while overriding the default behaviour.. 
  //   not this way, at least (with SSR).
  //   use {{#with getPost}} to 
  Template.view_post_server.helpers({
    'getPost' : function(id) {
      return Posts.findOne({_id : id});
    }
  });

  Router.map(function() {    
    this.route('view_post', {
      path: 'post/:id',       // post/:id  i.e. post/123
      where: 'server',        // this route runs on the server
      action : function() {
          var request = this.request;

          // Also taken from MDG's spiderable package.
          if (/\?.*_escaped_fragment_=/.test(request.url) ||
          _.any(userAgentRegExps, function (re) {
            return re.test(request.headers['user-agent']); })) {          

            // The meat of the SSR rendering. We render a special template
            var html = SSR.render('view_post_server', {id : this.params.id});
            var response = this.response;
            response.writeHead(200, {'Content-Type':'text/html'});
            response.end(html);

          } else {
            this.next(); // proceed to the client if we don't need to use SSR.
          }         
      }
    });
  });          


}

if(Meteor.isClient) {
  Router.map(function() {
    this.route('home');
    this.route('view_post', { // same route as the server-side version
      path: 'post/:id',       // and same request path to match
      where: 'client',        // but just run the following action on client
      action : function() {
          this.render('view_post'); // yup, just render the client-side only 
      }
    });
  });
}

ssr_test.html

<head>
  <title>ssr_test</title>
  <meta name="fragment" content="!">
</head>
<body></body>
<template name="default">
    {{> yield}}
</template>
<template name="home">
</template>
<template name="view_post">
    hello post {{is_server}}
</template>
<template name="view_post_server">
    hello post server {{is_server}} 
</template> 

结果:

我在http://ssr_test.meteor.com/上传了该应用以查看它的实际效果,但在使用SSR时似乎崩溃了。对于那个很抱歉。如果您只是将上面的内容粘贴在Meteorpad上,那么工作正常!

屏幕:

Client-side Server-side

这是Github Repo:

https://github.com/electricjesus/ssr_test

克隆并运行!

答案 1 :(得分:0)

SSR缺乏现实生活中的例子,但这是我如何运作的。

if (Meteor.isServer)
{
    Router.map(function() {
        this.route('postserver', {
            where: 'server',
            path: '/p/:_id',
            action: function() {
                // compile
                SSR.compileTemplate('postTemplate', Assets.getText('post_page.html'));
                // query
                var post = Posts.findOne(this.params._id);
                // render
                var html = SSR.render('postTemplate', {title: post.title, body: post.body});
                // response
                this.response.writeHead(200, {'Content-Type': 'text/html'});
                this.response.write(html);
                this.response.end();
            }        
        });
    });
}

资产记录在此处:http://docs.meteor.com/#assets