Ember.js Template Imports: Part 6

Given the tradeoffs in the space, what is the best set of compromises we can make?

Assumed audience: Other members of the Ember.js and Glimmer.js communities. (Others are welcome to read and chime in, of course, but this is absolutely an “in-house” discussion!)

Over the past month, I have systematically examined the tradeoffs of the proposed options for Ember and Glimmer’s template imports design:

  1. Introducing the series and walking through the formats.
  2. Which template imports design has the biggest set of wins for teaching and understanding components?
  3. Evaluating the tradeoffs of template language designs for tooling.
  4. Keeping, and improving on, one of Ember’s fundamental commitments  —  and biggest strengths: its integrated testing.
  5. What about styles? (A bonus post!)

In this final part, I am going to pull all of those threads together and synthesize them into my conclusion: that we should use <template>. Not because it’s perfect (none of the options are! This is software engineering!) but because it strikes the best balance across all these axes.


When I first started discussing these options with people a few years ago, after the strict mode and initial template imports RFCs were opened, I had a strong bias toward the hbs template literal strings design. I have since then come to think that hbs is the second-worst option, with only imports-only being worse — and that’s iffy, because the problems with hbs are so bad in my view! I also originally very much disliked SFC designs, but have now come to see them as better than the hbs design in many areas, and if it weren’t for a couple key limitations they might be my favorite. And the <template> proposal moved from being my second-least-favored proposal to the one I think we should adopt.

This was the result of discussing and thinking on all the tradeoffs I’ve laid out over the past few weeks in this series: what works best and has the fewest problems pedagogically? implementation-wise? for integrating with styles? for migrating existing users? for language server support?

I sympathize with people who still like other proposals better. Those feelings, in many cases, mirror my own initial responses in various ways, even if the details differ. I also expect that no matter what we choose, some people will be unhappy. That could include me! I continue to believe it is most important that we choose one of these formats and execute on it — even if that ends up being a decision in a direction I think is misguided.

That gets at something important, though: in order to make a decision, we simply have to evaluate the tradeoffs around these designs and do the best we can with the constraints we have. That’s why just use JSX isn’t one of the options I’ve discussed: JSX doesn’t work with the constraints of the Glimmer VM today. It’s also why I haven’t spoken at all about the aesthetics or questions of taste: we will likely all differ on which approach we think looks and feels nicest, and those differences are likely intractable. If you think the hbs proposal looks nicest, and I think SFCs look nicest,1 how could we possibly persuade each other? There is, as the saying goes, no accounting for taste.


With that in mind, let’s review the conclusions I drew in each of the earlier parts of the series — once again in tabular form:

Consideration <template> Template literals SFCs Imports-only
Progressive Disclosure Good Bad Very good Good
JavaScript semantics Good Good Good Very bad
Scope semantics Very good Bad Okay Good
Semantic mismatch Yes/HTML/tractable Yes/JS/intractable No No
Syntax
JS working working working not working
templates working working working working
Linting
JS partial partial partial no
templates no no no yes
needs custom parser yes yes yes yes
Formatting
JS no partial partial no
templates no partial partial no
needs custom parser yes yes yes yes
LS effort small none medium small
Server-side requires compilation yes for all formats, including hbs
shared syntax for tests yes yes no no
Styling Everything just works” for all formats

When you put all the pieces together like this, I think it’s fairly obvious why I ultimately concluded that <template> is the best choice. In every overarching category except for formatting, it is either comparable to the other choices or substantially better. It’s not perfect. It’s more work in a few spots than the alternatives, and in some other cases it’s just kind of the same as the alternatives. But it does come out the best overall.


As a final note, I think it’s worth considering the relationship between the different categories. Tooling costs are real, but they’re something we address straightforwardly by building some software. We’re software developers; we’re very good at building software! While there are some ongoing costs to maintaining software, they’re small and tractable, and they only fall on the people who maintain those tools.

By contrast, the problems of teaching and understanding are ongoing, and distributed. Every new developer who enters the Ember/Glimmer ecosystem will have to pay them — for as long as we use whatever format we choose here. In my view, that makes the case for <template> even more compelling: it’s not just that it comes out the winner in a general analysis (though it does), but that it comes out by far the winner in the most important and least-“solvable” category.

As ever, I’m happy to discuss this — and the series as a whole! — on the Ember forums or in Discord. And keep your eyes open for the RFC I’ll be opening in the next few weeks advocating that we ship <template> as the officially-supported syntax and as part of Ember’s upcoming Polaris edition!


Notes

  1. This is in fact what I think: SFCs look nicest. But that doesn’t make them the best decision. ↩︎