eta icon indicating copy to clipboard operation
eta copied to clipboard

Precompiling templates?

Open henderea opened this issue 2 years ago • 6 comments

Is your feature request related to a problem? Please describe. Version 3.x seems to have dropped support for the compile function, which is preventing me from using it to precompile templates for use in frontend code.

Describe the solution you'd like I would like a way to take a filename and compile it into a function, which I could then call toString() on to get something I can put in a file. This is what I have in 2.x (used in a gulp command; note that I have import { compile as etaCompile } from 'eta'; at the top of my gulpfile):

var compiledFunction = etaCompile(contents, {
    filename: file.path,
    include: false,
    includeFile: false
}).toString();```

**Describe alternatives you've considered**
My only option right now is remaining on 2.x.

henderea avatar Dec 18 '23 19:12 henderea

@henderea thanks for the question! I think this should be possible using eta.compile and calling toString() on the result.

bgub avatar Dec 18 '23 20:12 bgub

Well, at the very least, there's no named export named compile in 3.x. It complained about that when I tried running gulp after updating eta to the latest 3.x. I didn't try seeing if the class it exports had a compile method available, but I didn't see any such method in the 3.x docs.

To be clear, it all works fine with 2.2.0 and earlier. I'm just looking for a 3.x equivalent so I can upgrade.

henderea avatar Dec 18 '23 21:12 henderea

@henderea methods in Eta v3 moved to be part of an Eta class. Try something like this.

var { Eta } = require('eta')

const eta = new Eta()

const template = 'hello <%= it.name %>!'

const compiled = eta.compile(template)

// these two are equivalent:
eta.renderString(template, {name: 'Ben'})
// and
compiled.call(eta, {name: "Ben"})

// Now if you want to get the function as a string
compiled.toString()

Basically you'll need to call const compiled = eta.compile(template) and then to get the result run compiled.call(eta, data)

bgub avatar Dec 20 '23 03:12 bgub

Is it actually necessary to set the this to eta? Because I want to run the generated functions in the browser without loading in the whole eta instance. I'll probably just stick with 2.x.

henderea avatar Dec 20 '23 12:12 henderea

@henderea it is necessary to set this to eta, but remember that Eta is only 3KB minified and Gzipped. You could also look into using eta/dist/browser.umd.js.

bgub avatar Dec 20 '23 23:12 bgub

@henderea FWIW, here is how I would add Eta SSR support to my framework:

import { Eta } from "eta";
import { File } from "rcompat/fs";

const eta = new Eta();

const template = `<% if (it.user) { %>
  <h2><%= it.user.name %></h2>
<% } %>`;

await File.write("./compiled.js", `
  import { Eta } from "eta";
  const eta = new Eta();

  ${eta.compile(template).toString()}

  export default (props, options) => anonymous.call(eta, props, options);
`);

import("./compiled.js").then(imported => {
  // -> <h2>foo</h2>
  console.log(imported.default({ user: { name: "foo" }}));
})

terrablue avatar Jun 07 '24 11:06 terrablue