Published 6/22/2023
Introducing Eta v3
The next version of Eta, an embedded JS template engine, brings API and documentation improvements.
Background
Today, Eta is my most popular and widely used open-source project. But when I first published it 3 years ago, it wasn't one of my primary focuses. In fact, I created Eta as a slimmed-down variation of Squirrelly, a more complex template engine with features like helpers and filters.
As time passed, I realized that for most projects, an embedded template engine was actually a better fit than something more complex. Projects which needed complex or client-side HTML processing typically used a framework like React or Vue. Eta's performance and low bundle size, meanwhile, made it a great fit for projects which needed fast processing, low memory usage, or to handle non-XML languages.
At the same time, Eta had become increasingly popular thanks to its speed, Deno support, and syntactic advantages over EJS. Given those factors, I decided to make Eta my main focus. I spent time writing tutorials, fixing issues, and polishing documentation.
After several years and some time spent away from programming as a missionary, I finally had time to work on Eta again. I decided to make some big changes to the project, including the build system, API, and documentation.
Build System Updates
Despite Eta's advantages and features, it had some big problems. One such problem was the build system. Complex and unwieldy, it was difficult to maintain and update. I dealt with complex configuration files and the necessity of transpiling a version specifically for Deno.
Changes in version 3:
- Using microbundle to bundle the library helped me avoid the need for complex configuration files.
- Using GitHub Actions to run tests and collect coverage allowed me to consolidate the services I used.
- By setting
allowImportingTsExtensions: true
intsconfig.json
, I was able to avoid using Denoify for a separate Deno build.
API Changes
Another problem was the API. Simple methods like eta.render()
had many function overloads, making types difficult to infer and usage unintuitive. A custom configuration object could be passed in when calling user-exposed functions like render
, parse
, and compile
. In practice, that meant the user-provided configuration had to be merged with the default configuration every time any of those functions was called.
Changes in version 3:
- There's only one export, a named class called
Eta
. This class has a single constructor, which processes a configuration object and generates template caches at instantiation time. - The
render()
andrenderAsync()
functions now have a single function signature.- In Eta v2,
render()
andrenderAsync()
could be used to render either named templates or template strings. Eta v3 introduces two new functions to render template strings:renderString()
andrenderStringAsync()
.
- In Eta v2,
- The
readFile()
andresolvePath()
functions, which Eta uses internally, can be overridden as class methods by the user. - Internal variables and methods inside each compiled template are stored in the
__eta
object, rather than across several variables including__res
. - Rather than allowing users to specify one
root
directory and multipleviews
directories, users may just specify a singleviews
directory. This directory is used as the root directory for all template resolution. All template files must be inside this directory or a subdirectory of it, improving template security and reducing expensive file-lookup operations.
Developer Experience Changes
One of the biggest changes in Eta v3 was the addition of detailed runtime errors (inspired by EJS). Consider a template like the following, which will throw because of an undefined variable:
Eta v2 would throw an error with some generic info, but it wasn't incredibly helpful. In contrast, Eta v3 throws a detailed error with the template name, line number, and error message:
Documentation Changes
The documentation for Eta v2 was extensive but very difficult to navigate. Information about the project was split over 40+ (!) documentation pages, found in multiple folders spread across 3 different website sections.
The documentation for Eta v3 takes up 9 pages, all found in the same part of the website (eta.js.org). Topics like template syntax and API overview are covered in a single page, rather than being split across multiple pages.
The Future of Eta
I'm proud of the changes included in Eta v3, and of the project as a whole. Much thanks to those who contributed to the project through PRs, issues, and suggestions. Additional thanks to projects like ejs, from which Eta continues to draw inspiration.
I see Eta as mostly feature-complete at this point, though I'll continue to fix bugs and add some small features. I'd encourage current users of the library to upgrade to v3, and I hope new users will find Eta to be a great fit for their projects.
Links
If you liked this article, don't forget to share it and follow me at @nebrelbug on X!