Andreas Lundblad
Jun 17, 2018

Why I hate Shopify's Liquid Template Language

After writing a few hundred articles over at Programming.Guide using Jekyll / Liquid, I’ve concluded that I absolutely hate Liquid. Here’s a non-exhaustive list of my pet peeves…

Horrible Arithmetics

I mean…

{% assign x = a | plus: 100 | divided_by: y %}

…come on? Any sane language would allow {% assign x = a + 100 / y %}.

No Parenthesized Expressions

Since there’s no concept of operator precedence, you’d expect to at least be able to do

{% assign x = a | plus: (100 | divided_by: y) %}

but nope.

Terrible String Handling

Almost everything is a string, yet string handling is horrible. Want to insert a newline? \n? – No. The best way is to actually do

{% capture newLine %}
{% endcapture %}

and then use newLine.

Expressions vs Variables

Sometimes a variable is the only acceptable expression. You can’t for instance do

{% for item in items | sort: "price" %}
{% endfor %}

You must store the sorted array in a temporary variable. Same limitation for filter arguments, include arguments, if statements, …

Negate Boolean Values

You can express ‘and’ and ‘or’, but not ‘not’. Someone must have realized this shortcoming and introduced {% unless ... %}, which is {% if not ... %}. Unfortunately this still doesn’t allow you to express ‘if a or not b’. Sigh…

All Variables are Global

This means that whenever I {% include ... %} a file, I risk messing up all my current variables. It also makes it impossible to use variables in recursive includes (like when rendering menus or comment trees) since assignments in inner includes will overwrite variables in the outer includes.

No Object Literals

There is a concept of objects / maps, but there’s no way to create them yourself. An expression like {{ x | inspect }} might give you

{ "a" => "b" }

Yet there’s no way to express something like

{% assign x = {"a" => "b"} %}

No Array Literals

There’s no way to write array literals. This is for instance invalid:

{% assign arr = ["a"] %}

You have to resort to something ugly like: "a" | split: "X".

Since "" | split: "X" should logically result in [""] it would seem even trickier to produce the empty array. Luckily(?) split is buggy, and "" | split: "X" actually returns [].

Perhaps that’s by design? Maybe split filters out empty elements? – No, ",a" | split: "," gives ["", "a"]… go figure.

Horrible Comment Syntax

And the award for the worst comment-syntax of the century goes to…… Liquid! It’s not particularly tempting to comment the code when you have to write

{% comment %}Simple explanation{% endcomment %}

No While Loops

No while loops? Seriously? Not even something that resembles it? I see where they came from. Shopify don’t want “designers” to bring down servers by creating infinite loops, but recursive includes are allowed! Just as the recursion depth is capped, you could cap the number of iterations!