handlebars.js icon indicating copy to clipboard operation
handlebars.js copied to clipboard

Load precompiled templates from Typescript

Open xjrcode opened this issue 5 years ago • 6 comments

For anyone trying to load precompiled templates from typescript (for sending an email for instance):

  1. You have to precompile with the -c option: handlebars templates/*.handlebars -f templates/precompiled.js -c handlebars/runtime
  2. Load the Handlebars runtime and then the templates file:
import * as Handlebars from 'handlebars/runtime';
import './templates/precompiled'; // load templates
  1. Use as always: Handlebars.templates['name-of-file-without-extension'](data)

I hope this helps you and you don't waste many hours like me.

xjrcode avatar May 29 '19 10:05 xjrcode

Thanks, I have marked this as "docs-needed". Maybe it will find its way into https://github.com/handlebars-lang/docs/ some day

nknapp avatar Jul 02 '19 19:07 nknapp

Would that go like maybe under integrations? https://handlebarsjs.com/installation/integrations.html

papasmile avatar Feb 17 '20 17:02 papasmile

What is templates/precompiled.js?

mykeels avatar Apr 23 '20 14:04 mykeels

Saw a couple of different of answers floating around... Replace double back ticks with single back ticks! To generate a template use this const Handlebars = require('handlebars'); const fs = require('fs'); const addTemplate = async (templateName) => { const templateFile = await fs.promises.readFile(./path/to/template); const templateString= templateFile.toString(); const precompiledPath = ``./precompiled/${templateName}.js``; const precompiledFileString = Handlebars.precompile(templateString).toString(); await fs.promises.writeFile(path.join(precompiledPath, ``${templateName}.js``), ``module.exports = ${precompiledFileString}``, {encoding: 'utf8'}); }

To read from the template use this const Handlebars = require('handlebars/runtime'); const profileTemplate = require('./precompiled/profile.js') const getTemplate = (templateName, data) => { const template = Handlebars.template(templateName); const compiledTemplate = template(data); return compiledTemplate }

jhiggs15 avatar Nov 11 '22 02:11 jhiggs15

I just spent a solid day on this. Gonna post here and maybe it'll make it into the docs one day. I have a specific need of loading precompiled templates only if I need them, also because I don't know if they'll be available until I evaluate a specific conditional. This is for a lambda@edge function in AWS.

Here is an example template that i have in a file called before.handlebars

{"bar": "{{header "user-agent"}}"}

I've run the following command against this file

npx handlebars before.handlebars -f before.precompiled.js -c handlebars

To use this:

import Handlebars from 'handlebars'
...redacted....
if (config.eventing && config.eventing.events?.before_decision) {
            // https://stackoverflow.com/a/36299373/3689435
            require("./before.precompiled.js")

            const populated = Handlebars.templates["before"]({
                headers: request.headers,
            })

            console.log(populated)
        }

I'm not that familiar with the difference between handlebars and handlebars/runtime. Just make sure that which ever one you choose to use, the import at the top of the file and the -c flag on the cli are the same, else this won't work.

My lambda@edge function is written in typescript and compiled with esbuild and once I figure this out, I had no problem. I don't need any special bundlers or loaders.

ddouglas avatar Aug 18 '23 02:08 ddouglas

@ddouglas Although not related to this issue, I would like to suggest not to use Handlebars to generate JSON output.

It is much easier and probably more efficient to use

const populated = JSON.stringify({
    bar: request.headers["user-agent"]
})

in your case.

If you would like to see this in the docs, feel free to open a PR at https://github.com/handlebars-lang/docs/.

@papasmile I would put it after https://handlebarsjs.com/installation/precompilation.html#precompiling-templates-inside-nodejs I would not consider "TypeScript" an integration. This is more related to pre-compilation than to build-systems.

nknapp avatar Aug 18 '23 07:08 nknapp