After hundreds of hours of development, I finally released my open-source project last week. Eta is a pluggable, lightweight, and super-fast JavaScript template engine I created to serve as an alternative to doT and EJS.
Before I get into discussing my development journey, though, let me outline some differences between Eta and EJS.
Eta vs EJS
Eta's syntax is very similar to EJS' (most templates should work with either engine), Eta has a similar API, and Eta and EJS share the same file-handling logic. Here are the differences between Eta and EJS:
- Eta is more lightweight. Eta weighs around 2KB gzipped, while EJS is 4.4KB gzipped
- Eta compiles and renders templates much faster than EJS. Check out these benchmarks: https://ghcdn.rawgit.org/eta-dev/eta/master/browser-tests/benchmark.html
- Eta allows left whitespace control (with
-
), something that doesn't work in EJS because EJS uses-
on the left side to indicate that the value shouldn't be escaped. Instead, Eta uses~
to output a raw value - Eta gives you more flexibility with delimeters -- you could set them to
{{
and}}
, for example, while with EJS this isn't possible - Eta adds plugin support
- Comments in Eta use
/* ... */
which allows commenting around template tags and is more consistent - Eta parses strings correctly. Example:
<%= "%>" %>
works in Eta, while it breaks in EJS - Eta exposes Typescript types and distributes a UMD build
- Custom tag-type prefixes. Example: you could change
<%=
to<%*
Features Eta and EJS share
- Async support
- Partials support
- File-handling support
- Eta borrows its file-handling code from EJS, which has over 1.5 million downloads / week. It's pretty reliable 😉
- Express.js support
- EJS syntax-highlighting tools work to some extent with Eta
Why did I build Eta?
My journey started around 2 years ago, when I first created a template engine called Squirrelly. After hundreds of hours of performance benchmarking and trying dozens of different parsing methods, I was finally able to break the speed of all other popular template engines.
Over the last year, I've been working on the next version of Squirrelly, which adds some important features like template inheritance and better string parsing. While benchmarking Squirrelly, I realized that it was significantly faster than other template engines like EJS -- even though it supported helpers, filters, template inheritance, etc.
I decided to take the framework behind Squirrelly (all of the behind-the-scenes code) which I had already optimized and tested extensively, and create a simple embedded template engine on top of it. The new template engine would be more configurable than most other template engines, extremely lightweight, very fast, and more reliable than most other template engines.
I named the new template engine "eta" for a few reasons.
1) Eta means "tiny" in Esperanto, and Eta is a tiny template engine
2) Eta is the name of a letter in the Greek alphabet, which I use as a cool logo
3) "Eta" is 3 letters long, which makes it easy to write template files (ex. footer.eta
)
Within several weeks, I was able to create Eta. Because I didn't have to worry about Squirrelly's advanced features, Eta took significantly less time to create and test. Using Docusaurus v2, I was able to throw up a documentation site and write a playground.
A few lessons learned
- In JavaScript (at least the v8 engine) regular expressions are super optimized and are significantly faster than even looping through every character in a string and doing something with it
- TypeScript catches a lot of stupid errors
- Running code coverage tests helps find unnecessary (dead) code
- Performance can be improved significantly by lots of trial-and-error testing
-
with () {}
in JavaScript slows down execution and can cause confusing bugs
Eta's Stack
- Written in TypeScript
- Compiled with Rollup (which, for libraries, creates much smaller builds than Webpack)
- Minified with rollup-plugin-terser
- Tests with Jest
- Code-coverage with Coveralls
- Travis CI for Continuous Integration
- Prettier for formatting
- ESLint with StandardJS compatibility for linting
- TypeDoc for automatic API Doc Generation
I hope you enjoyed reading about my journey to create Eta! If you need an embedded JavaScript template engine for a future project, consider using Eta instead of a library like EJS or doT.
Top comments (15)
Hey, Ben, congrats on building Eta, sounds like it is bound for great success. I started learning web development (I'm a chemical engineer working with investment brokerage) a few weeks ago through Udemy. I came across EJS and found it rather interesting. However, it looks really odd to me to have all that Javascript within the HTML code. I therefore wonder if EJS is really widely used or is just a niche framework, for very specific purposes. Thanks.
Thanks (and sorry for the late reply)!
EJS and lodash.template (a similar alternative library) each have about 6 million downloads per week. I think many JavaScript developers choose to use them because -- even if JavaScript inside HTML is a little bit strange-looking -- they know it'll be readable to other JavaScript developers, rather than making them learn some new template syntax.
A great example of a project that uses Eta currently is Docusaurus, which uses Eta (ex. in github.com/facebook/docusaurus/blo...) to generate server-side builds.
I must truly say that Eta is amazing. Everything that annoyed me in EJS is now no more.
I just changed the tags to
{{ }}
because i know that I won't ever use it and it's faster to type. Even tho I haven't used handlebars.Keep it up, I just hope this project will keep going, it has such a huge potential! For me it's already huge.
Cool, I was wondering if it was possible to generate static files with Eta (pre-build).
I have a project where users can create posts with a wysiwyg editor.
What I want to achieve is try to take that post, inject it into a predefined Eta template and export a static (HTML) page from it (with header, footer, sidebar...). Then I would host that page on a CDN for quick access.
Since the content will never change there is no need to compile the HTML at runtime.
I was wondering if something like that would be possible with Eta?
User creates post -> server compiles it to a static HTML file from pre-define Eta templates -> server uploads to CDN -> user can access page from CDN
Would this be suited for my needs? Thanks!
It sure would! One of the best use cases for Eta is generating static content. Right now, for example, Docusaurus uses Eta to generate static HTML for SSR builds.
It looks like a loooooot of work! Congratulations for the launch, it looks slick 👍
Thank you!
can it re-renders template on state/object change ?
If you manually re-render it or implement a state listener (like React). That kind of functionality is more common in Virtual-DOM engines.
Hi Ben, sounds good. I want to use it in 11ty, what do you offer?
Thank you!
Right now, Eleventy doesn't support Eta. However, you can upvote the enhancement request here (github.com/11ty/eleventy/issues/1416) or submit a PR to add support!
Great job Ben. I tested it, it's fantastic!
Why don't you create an Eta runtime version (like squirrelly) for complied templates? :)
Thank you!
I thought about creating a runtime version, but ended up deciding against it because even the full version of Eta is quite lightweight.
It would be quite easy to create a separate runtime version though... if you're interested in creating one I'll link to it!
Very nice
Thanks!