Skip to content

Instantly share code, notes, and snippets.

@mpj
Last active October 24, 2018 15:19
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mpj/d37bb421efe1e3eda4a6da7e18864362 to your computer and use it in GitHub Desktop.
Save mpj/d37bb421efe1e3eda4a6da7e18864362 to your computer and use it in GitHub Desktop.
Templating critique

Thoughts on Templating languages

I get a lot of questions about what I think about Vue.

I won't comment too much on Vue in general because I'm not familar enough with it, but I'm very familiar with templating systems, and in articles praising Vue, the fact that it uses templating system instead of JSX is almost always cited as a reason to choose Vue. This drives me up the friggin' wall, because the negative side effects of templates are not communicated or discussed. JSX exists for good reasons. To me, JSX is a great simplification and clear improvement over templates.

Template languages are often sold on looking superficially good. I recently ran across yet another one of these articles citing the wonders of Vue, and especially templates. In this article, this JSX example is included:

render() {
  let { items } = this.props
  
  let children
  if (items.length > 0) {
    children = (
      <ul>
        {items.map(item =>
          <li key={item.id}>{item.name}</li>)}
      </ul>
    )
  } else {
    children = <p>No items found.</p>
  }
  return (
    <div className="list-container">
      {children}
    </div>
  )
}

The article berates that JSX example for being verbose, and then goes on to cite this Vue example as a counter example:

<template>
  <div class="list-container">
    <ul v-if="items.length">
      <li v-for="item in items">
        {{item.name}}
      </li>
    </ul>
    <p v-else>No items found.</p>
  </div>
</template>

This is very disingenuous by the author, since the first example is written in a very verbose way. Written in a more concise manner, it would look like this:

let ListContainer = ({ items }) => {
  <div className="list-container">
    {items.length === 0
      ? <p>No items found</p>
      : <ul>
        {items.map(item => 
          <li key={item.id}>{item.name}</li>
        )}
      </ul>
    }
  </div> 
}

I'm not sure if the author of the article is being intentionally misleading, or if he picked the JSX code from some React tutorial online. I'm going to give him the benefit of the doubt and assume the latter. If so, the original JSX above was probably written in a verbose way in order to demonstrate how things work to the reader - when explaning programming tooling, you don't want terseness, you want to explain things in clear ways with as little magic as possible.

The Vue example, however, doesn't explain much about HOW the heck it actually WORKS. I know how Array.map works, but what is v-for and what is that syntax in the attribute? Yes, it's easy enough to understand WHAT this indivudual template does, because it reads a bit like English, but when you actually have to start writing and working with these templating languages, you development speed will slow down to a crawl, because you will now have to spend time learning (and often extending) the templating langauge. Yes, it's not a big language, but it's still a bloody language that I have to learn. In JSX, there is very little to learn, and I can then exploit my existing JavaScript knowledge and tooling.

For example, let's say that I want to filter out items that are inactive. JSX is just JavaScript, so I just filter:

let ListContainer = ({ items }) => {
  <div className="list-container">
    {items.length === 0
      ? <p>No items found</p>
      : <ul>
        {items
          .filter(item => item.active) // <-- LINE ADDED
          .map(item => 
            <li key={item.id}>{item.name}</li>
          )
        }
      </ul>
    }
  </div> 
}

How to do this in the Vue template? I honestly have no idea. I wanted to provide an example here but 10 minutes of googling later I still cannot find how to do it. It might be possible to figure out somehow, but the point is that I already HAVE Array.filter! This knowlege problem exists JUST because we've invented an entire custom language to use here instead of just using JavaScript.

The entire PHP community learned this 10 years ago when most sane PHP programmers stopped using Smarty (http://www.smarty.net/) when they realized that PHP itself was excellent as a templating language.

JavaScript is no different here - it's perfectly good as your templating language, don't invent yet another niche language.

@mpj
Copy link
Author

mpj commented Apr 21, 2017

Not mentioned so far: vue's templating allows you to just plop in a vue.js script tag into any page and get going. No need for a build system.

With JSX, you need the entire babel compiler, which adds too much startup time. Or you can go with straight react, but who wants to do that? So, react is kind of limited to full-borne projects with a build system, which is a shame.

@panta82 This comes up often, but it's an argument that is foreign to me and I need a bit more context to understand. To be, having a transpilation/build step is something that you HAVE to add to an application, even pretty early on - at least the ones that are complex enough to need a virtual dom. I'm trying to understand here.

If you do not have a build step, you cannot:

  • minify the application for deployment, so the clients will get unoptimized JS
  • use any modern JavaScript features, and have to be extremely mindful of browser support all the time
  • use npm modules

Because of these things, it seems very strange to me not to have a compiler step because it provides so much benefit. I would love to hear a bit more about the realities of the people that pick Vue because they feel that React imposes transpilation on them, and how they work without transpilation.

Copy link

ghost commented Apr 23, 2017

@mpj You say you like JSX because it lets you use JavaScript instead of using a new syntax to do operations that already exist in JS. Then I think you would love Hyperscript since it's 100% JS and not "almost JS" like JSX :). Mithril is a library that uses Hyperscript to describe HTML and it's very easy to learn and use.

@westtrade
Copy link

westtrade commented Apr 25, 2017

let ListContainer = ({ items }) => {
  <div className="list-container">
    {items.length === 0
      ? <p>No items found</p>
      : <ul>
        {items
          .filter(item => item.active) // <-- LINE ADDED
          .map(item => 
            <li key={item.id}>{item.name}</li>
          )
        }
      </ul>
    }
  </div> 
}

excuse me, but it's look like crazy unreadable thing

@jefkoslowski
Copy link

@mpj The same way of thinking can be applied to ORM vs SQL?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment