我可以热部署 Meteor 客户端 HTML 文件吗?

问题描述:

Meteor 非常了不起,因为您可以在本地开发时手动更新 HTML 文件,这些更改会在您保存文件时立即生效.我想采用相同的功能并将其带到我们部署的环境中.原因是我们希望允许我们的客户在无需重新部署应用程序甚至不知道它是 Meteor 应用程序的情况下更改 UI.他们可能会向列表视图添加新字段、向表单添加新字段、更改标签等.

Meteor is pretty amazing in that you can update the HTML files manually while developing locally and those changes take affect immediately when you save the file. I would like to take that same functionality and bring it to our deployed environment. The reason being that we would like to allow our client to make changes to the UI without having to redeploy the application or even know it's a Meteor app. They might add new fields to a list view, new fields to a form, change labels, etc.

到目前为止,我已经为他们创建了一种方法,可以使用 DSL 来调用 REST 服务来描述这些更改并将其保存在 Mongo 中.然后我们有一个引擎,它将动态创建 HTML 模板来实现它.一切都很好.

Thus far, I've created a means for them to call a REST service using a DSL to describe those changes and save it in Mongo. Then we have an engine that will dynamically create the HTML templates to implement it. That all works great.

接下来,我尝试根据我对 Meteor DB 的订阅来热部署 Meteor HTML 文件,该数据库存储了可以按需更改的内容.是否可以动态更新 Meteor 客户端文件系统,以便我可以实现热部署?

Next, I'm attempting to do a hot deploy of Meteor HTML files based off a subscription I have with the Meteor DB which stores things that could change on demand. Is it possible to update the Meteor client filesystem on the fly so I can achieve a hot deploy?

在服务器发布方法上执行以下操作会导致 ENOENT: no such directory 错误:

Doing the following on the server publish method results in an ENOENT: no such directory error:

var result = decodeHTML(cheerio.html());
console.log(result);

// Output to file
fs.writeFile('../client/app/client/templates/request-base-template.html', result, function (err) {
    if (err) {
        console.log("error: " + err);
    }
    else {
        console.log("File saved successfully");
    }
});

将文件保存到磁盘以期待热代码推送重新加载"绝对是一种错误的方式.

Saving files to disk to expect "Hot code push reloads" is definitely a wrong way to go here.

Meteor 在开发模式下提供文件监视,它会重新编译您的整个应用程序并在您的浏览器中刷新页面,但这是为了开发人员的方便,而不是为了您的应用程序的运行时使用.事实上,在生产环境中部署时甚至没有提供文件监视功能.

Meteor provides file-watching in the development mode, and it will recompile your whole app and refresh the page in your browser, but this is made for the developer convenience and not for the run-time use by your application. In fact, file-watching is not even shipped when deployed in production.

但这里有一种实现您的用例的方法.这需要更深入地了解 Meteor 在幕后为您做什么.

But here is a way to implement your use-case. It would require some deeper understanding of what Meteor is doing behind the scenes for you.

首先,您需要意识到 Meteor 在构建时将您的模板(空格键模板)编译为自己的 JS DSL(HTMLJS).每个基于结构的模板都会发生类似的事情,无论是在运行时还是在构建时编译它们.Meteor 在构建时执行此操作以提高效率.您可以在Meteor 手册,Blaze 章节中阅读更多相关信息;

First of all, you need to realize that Meteor compiles your templates (Spacebars templates) to its own JS DSL (HTMLJS) in the build time. Similar things happen to every structure-based templating, either you compile them in run-time or in build-time. Meteor does it in build-time to make things more efficient. You can read more about it in Meteor Manual, Blaze chapter;

这里的要点是:如果你有一个模板

The high-level point here is: if you have a template

<template name="bla">
  Hello {{name}}!
</template>

.. 它会被编译成这样:

.. it would be compiled to something like this:

Template.__define__("bla", (function() {
  var view = this;
  return [ "Hello ", Blaze.View(function() {
    return Spacebars.mustache(view.lookup("name"));
  }), "!" ];
}));

明白了吗?太好了.

现在,您需要从用户那里获取这种模板,并将它们编译成这个基于 JS 的 DSL.您可以使用内置的 spacebars-compiler 包来完成.

Now, you need to get this kind of templates from users and compile them into this JS-based DSL. You can do it with the built-in spacebars-compiler package.

// on the server!
Meteor.startup(function () {
  // imagine your template is actually coming from database or where you store your user-generated content
  var template = "<p>Hello {{name}}!</p>";
  console.log(SpacebarsCompiler.compile(template));
});

如果您将 spacebars-compiler 添加到您的应用程序并运行它,它将打印一个很好的编译模板.这是一个现场演示:http://meteorpad.com/pad/4tHHAvjpcBQwLuN4K

If you add spacebars-compiler to your app and run this, it will print a nice compiled template. Here is a live demo: http://meteorpad.com/pad/4tHHAvjpcBQwLuN4K

完美,现在将这个编译好的模板以您想要的任何形式发送给客户端(通过数据库,通过 Meteor 方法或 REST API,没关系,只需将字符串发送给客户端即可).

Perfect, now ship this compiled template to the client in any form you want (through database, through a Meteor method or a REST API, it doesn't matter, just get the string to the client).

一旦它在那里,你就可以把它贴在任何你想要的地方!

Once it is there, you can attach it anywhere you want!

一种更简单的方法是在 JS 代码中注册模板:

One of the easier ways to do it is to register the template in JS code:

// on the client! pretend you got the compiledTemplate string from the server
var compiledTemplate = '(function() { var view = this; return HTML.P("Hello ", Blaze.View(function() {return Spacebars.mustache(view.lookup("name")); }), "!");})';
Template.__define__("myAwesomeTemplate", eval(compiledTemplate));

然后使用诸如 UI.dynamic 之类的东西在页面上呈现它.你可以在这里看到现场演示:http://meteorpad.com/pad/LQJuoooBQjSdJenfW

And then use things like UI.dynamic to render it on the page. You can see a live demo here: http://meteorpad.com/pad/LQJuoooBQjSdJenfW