Skip to content

Instantly share code, notes, and snippets.

@bakura10
Created November 17, 2017 18:29
Show Gist options
  • Save bakura10/c43062615c175c5e79075a24d368c8e6 to your computer and use it in GitHub Desktop.
Save bakura10/c43062615c175c5e79075a24d368c8e6 to your computer and use it in GitHub Desktop.
Shopify awesomeoness

DISCLAIMER: this is not really only about slate, just rough ideas on what I'd like to see in Shopify and that could be achieved in JS.

Hi everyone,

I had a talk with @t-kelly a few days ago and I'd like to expand on an idea that should represent what Slate could be in the future or what are the main frustration points in developing Shopify Themes.

Origin

We're now trying to develop more and more complex themes, both for the theme stores and clients. We're always trying to push the boundaries of what is possible with Shopify.

Sections and new variables such as product.options_with_values was a great way to achieve some awesome use cases. Alongside this, I've tried to improve my tooling: using Babel, removing jQuery completely from my new themes to write cleaner code...

At the same time the requirements for Shopify themes is stricter and stricter: a11y, lazy images... make the markup more complex and more redundant... and also less efficient as managing the DOM efficiently is hard.

Finally, I'm always feel guilty when I have to write that kind of codes:

capture d ecran 2017-11-17 a 19 09 43

Or manually re-rendering a cart in JavaScript...

Use a template engine !

Sure. I did. For two versions of our themes Kagami and Focal. I tried CartJS (https://cartjs.org/) which was just a small library to enhance the cart only.

But it was a full disaster (at least for Shopify themes in the theme store).

Merchants install app which makes assumptions on Liquid, merchants hire Shopify Experts who are not often experts, merchants ask app developers to do install...

This leads to so much support and incomprehension along our users that I had to rewrite everything in a hurry to remove those client-side template engine and fall back to spaghetti JavaScript. So, never again.

Example of Polaris

In the meantime I've also experimented a bit with Polaris, and I found it awesome. I love the concept of isolated components. It reduces duplication, help writing cleaner code... but obviously using React in Shopify themes would be an even more disaster from a support point of view.

Making Liquid a client-side language?

I think that an awesome addition to Slate (albeit really complex) would be to:

  1. Support component.
  2. Being an hybrid language that could work on client-side and server-side.

Components

Similar to section, one great addition would be to create components:

{% component 'Popover', title: 'Choose flavor' %}

Inside the component:

<div class="Popover">
  <h1>{{title}}</h1>
</div>

Component could also accept block when declared:

{% component 'Popover', title: 'Choose flavor' %}
  {% capture 'content' %}
     <select>
        <option>Vanilla</option>
     </select>
  {% endcapture %}
{% endcomponent %}

Inside the component:

<div class="Popover" aria-hidden="false">
  <h1>{{title}}</h1>

  <div class="Popover__Content">
    {{ content }}
  </div>
</div>

Component could have their own isolated JavaScript:

<div class="Popover" aria-hidden="{{component.isHidden}}">
  <h1>{{title}}</h1>
  <button on-click="close">Close</button>
</div>

<script>
class Popover extends Shopify.Component {
  this.isHidden = false;

  close() {
    this.isHidden = true;
  }
}
</script>

Client-side rendering

The main problemI I can is definitely keeping compatibility here... That's definitely not an easy task, and why I don't see Shopify switching to React or something like this... but if Slate could become a client-side template engine that understand Liquid syntax, or even built-in into Shopify theme... we could preserve the same syntax while having the advantage of modern JavaScript.

For instance, a cart section could include a component:

# cart-template.liquid section
{% component 'Cart' %}
# components/cart.liquid

<ul>
  {% for line_item in cart.items %}
     <li>
        <p>{{line_item.title}}</p>
        <p>{{line_item.price | money}}
        <button on-click="increaseQuantity({{line_item.quantity | plus: 1}})">Add one</button>
     <li>
  {% endfor %}
</ul>

<script>
  class CartComponent extends Shopify.Component {
     increaseQuantity(newQuantity) {
        // Do ajax call
        
        // Explicitly call a Shopify utility to refresh view (as for compatibility reason it could not)
        this.refresh();
     }
  }
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment