mde / ejs

Embedded JavaScript templates -- http://ejs.co
Apache License 2.0
7.74k stars 843 forks source link

Add a precompile step #743

Open terrablue opened 1 year ago

terrablue commented 1 year ago

Hi, is it possible to add a precompilation step like handlebars'? Such that it's possible to compile .ejs files once to JS, and then render them with different data.

As far as I can see, that would be pretty similar to ejs.compile, except that instead of constructing a function to be executed on the fly, the source code would be returned so that it can be saved to disk.

I don't mind submitting a PR if the idea is generally favored.

morandd commented 4 months ago

This is possible in Eta, by calling .toString() on the result of .compile(). This technique may work in EJS too? ref: https://github.com/eta-dev/eta/issues/268

terrablue commented 4 months ago

@morandd Hi, this is possible for Eta (see https://github.com/eta-dev/eta/issues/268#issuecomment-2154672195), but EJS here produces the following code:

function anonymous(data) {
      var include = function (path, includeData) {
        var d = utils.shallowCopy(utils.createNullProtoObjWherePossible(), data);
        if (includeData) {
          d = utils.shallowCopy(d, includeData);
        }
        return includeFile(path, opts)(d);
      };
      return fn.apply(opts.context,
        [data || utils.createNullProtoObjWherePossible(), escapeFn, include, rethrow]);
    }

This does not seem to me as something you can easily import and call, without at least knowing what utils is and where it can be imported from. Also, it doesn't look to me as though the compiled template is included (unlike with Eta).

morandd commented 4 months ago

you can easily import and call

What I did in Eta was

... .toString().replace("function anonymous(","function myFunction(")

then save that to a file myFunction.js then later I can import {myFunction} from './myFunction.js'.

Regarding the EJS utils object, if it's in scope as part of the closure when you execute myFunction() it should work.

I haven't done this in EJS so I'll stop talking now. (I just happened to see this thread while looking at another EJS Issue.) Good luck!