Easy way to precompile Emberjs Handlebar templates

2019-03-09 13:16发布

I'm enjoying emberjs a lot and would like to take the next step in a couple of my small, mobile apps and precompile my Ember/Handlebars templates as part of my build process.

I'd prefer to stay away from messing with Ruby and would like to use node.js as I'm more comfortable with using it.

I believe what I want to use is Ember.Handlebars.precompile, but unfortunately I'm unable to load the canonical ember.js file in a node environment. Example of a naive attempt from the node repl:

> var e = require('./ember');
ReferenceError: window is not defined
    at /Users/jeremyosborne/git/projects/ldls/client/lib/emberjs/src/ember.js:5:1
    at Object.<anonymous> (/Users/jeremyosborne/git/projects/ldls/client/lib/emberjs/src/ember.js:1596:2)
    --- stack trace, you get the idea ---

I think I've already figured out how to set them up in my code so that they work correctly with my views, I just want to compile them in an environment outside of a browser DOM.

In lieu of getting the canonical ember.js to load in node, are there a specific set of files that I can pluck from the ember repo and use to compile my templates?

EDIT I did a kluge fix that works great but gets an F for maintainability. I grabbed all the Handlebars code minus the reference to the window object. Then I followed with the Ember.Handlebars.Compiler code, replacing Ember.create with Object.create, exporting my Ember object, and viola things work seemingly great in node (as in it works and the functions produced are templates). But I don't consider this an answer to my own question due to the aforementioned maintainafail, so still open for answers.

EDIT 2 The above turns out to be a total fail. Perhaps there's something wrong in the procedure, but using Ember.Handlebars.precompile or Ember.Handlebars.compile doesn't work. The templates get made, but when I use the precompiled templates attached to Ember.TEMPLATES in my code, they do not work. I only seem to be able to get templates to work when they are explicitly passed in the modified script tags, as suggested on the emberjs.com site.

EDIT 3 I figured out what I was doing wrong. My answer is below.

8条回答
该账号已被封号
2楼-- · 2019-03-09 13:27

Look at the code for the official ember-rails gem at https://github.com/emberjs/ember-rails

While it's not a node.js project, it does show you how to precompile the templates using the Rails 3.1+ asset pipeline, and it includes all the necessary Javascript code that you would need to do it in Node without having to hack together a solution that you'd have to maintain on your own.

More specifically, look at vendor/assets/javascripts/ember-precompiler.js and lib/ember-rails/hjs_template.rb

I'm far from an expert on Node (obviously, Rails is more my thing).. but I think those two files should point you in the right direction. Basically, you're going to want to concatenate ember-precompiler.js (which acts as a "shim" for lack of a better word) with ember.js and then call EmberRails.precompile to compile your templates.

查看更多
爷的心禁止访问
3楼-- · 2019-03-09 13:31

I've written a grunt plugin called grunt-ember-handlebars that does exactly this. It pretty much mimics Garth's script, with one important difference:

It uses lib/headless-ember.js and lib/ember.js, which are maintained (at least for now) by ember.js to precompile default templates. If you don't want to use grunt, you can extract the relevant code from the precompile_handlebars helper in tasks/ember-handlebars.js.

查看更多
smile是对你的礼貌
4楼-- · 2019-03-09 13:33

Take a look at the npm package Ember-Runner

查看更多
看我几分像从前
5楼-- · 2019-03-09 13:35

window object can be mocked by jsdom

    var jsdom = require("jsdom").jsdom;
    global.document = jsdom("<html><head></head><body></body></html>");
    global.window = document.createWindow();
    global.$ = global.jQuery = window.$ = window.jQuery = require("jquery");
    global.Handlebars = window.Handlebars = require('handlebars');
    global.Application = window.Application = {};
    require('ember.js');

and now you can run anything from Ember including Ember.Handlebars.compile

查看更多
beautiful°
6楼-- · 2019-03-09 13:40

I wrote an official precompiler npm module for anyone else who might be wanting to do this w/ a recent version of ember.js

https://npmjs.org/package/ember-template-compiler

It's simple to install and use (example below)

npm install ember-template-compiler

var compiler = require('ember-template-compiler');
var template = fs.readFileSync('foo.handlebars').toString();
var input = compiler.precompile(template).toString();
var output = "Ember.TEMPLATES['foo'] = Ember.Handlebars.template(" + input + ");";
查看更多
贪生不怕死
7楼-- · 2019-03-09 13:43

Found a good enough solution to my problem that seems easy enough to maintain that I'll consider my problem solved.

Here's how I solved things:

  • Grab the minimal amount of code I need to precompile the ember templates.
  • Outline of the simple precompile procedure:
    • Load up the code with a var Ember = require('./my_ember_precompiler').Ember.
    • Get your templates as strings and compile them with var templateString = Ember.Handlebars.precompile(str).toString().
    • This will be different from app to app, but Ember seems to require registration of precompiled templates. After loading, for every created template, we need to register our templates. Basically wrap templateString in a call to Handlebars.template() and make sure this wrapped function is added to the Ember.TEMPLATES object.

The above is painless when it's automated in a script.

查看更多
登录 后发表回答