Alabhya Jindal

Frontend frameworks are useful

I thought that all frontend frameworks are bloat after being unhappy with the direction taken by React.

I feel very different today. I just moved Imgbar, my side project, from JavaScript to Svelte.

Imgbar

Imgbar is an image editor for inserting text into images. The first version of the project was made with Sinatra and SQLite on the server, JavaScript in the browser. I also used htmx for implementing the search feature.

Imgbar Screenshot

Today I removed all the server code and have decided to move the client code to Svelte. I’m pretty happy so far.

Let’s take a function from the old codebase and compare it to it’s Svelte counterpart.

JavaScript

function createTextareas() {
  const mgControls = document.getElementById('mg-controls');
  mgControls.innerHTML = '';

  texts.forEach((text, i) => {
    const mgControl = document.createElement('div');
    mgControl.classList.add('mg-control');

    const textarea = document.createElement('textarea');
    textarea.classList.add('mg-textarea');
    textarea.placeholder = `Text ${i + 1}`;
    textarea.name = `Text ${i + 1}`;
    textarea.value = text.value;
    mgControl.appendChild(textarea);

    const div = document.createElement('div');
    const input = document.createElement('input');
    input.type = 'color';

    input.name = 'fill';
    input.id = 'fill';
    input.value = text.fill;

    div.appendChild(input);

    mgControls.appendChild(mgControl);
    mgControl.appendChild(div);
  });
}

The function constructs textarea and input elements from a texts object. Distribution of markup in little functions like this across the project was becomgin unmanageable. It was difficult to quickly make changes.

Svelte

<div id="mg-controls">
  {#each texts as _, index}
    <div class="mg-control">
      <textarea
        bind:value={texts[index].value}
        name={`Text ${index + 1}`}
        class="mg-textarea"
        placeholder={`Text ${index + 1}`}
      ></textarea>
      <div>
        <input
          bind:value={texts[index].fill}
          name="fill"
          id="fill"
          type="color"
        />
      </div>
    </div>
  {/each}
</div>

The code is now a lot more readable and I can easily makes changes to the markup.

Revelations