eta-dev / eta

Embedded JS template engine for Node, Deno, and the browser. Lighweight, fast, and pluggable. Written in TypeScript
https://eta.js.org
MIT License
1.35k stars 60 forks source link

Precompiling templates? #268

Open henderea opened 6 months ago

henderea commented 6 months ago

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.
nebrelbug commented 6 months ago

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

henderea commented 6 months ago

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.

nebrelbug commented 6 months ago

@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)

henderea commented 6 months ago

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.

nebrelbug commented 6 months ago

@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.

terrablue commented 1 month ago

@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" }}));
})