DEV Community

Cover image for A Debrief on Svelte: Compile before Sending
dREWbxKewb
dREWbxKewb

Posted on

A Debrief on Svelte: Compile before Sending

Intro

When build a web app, one has to ask the question, what library or framework do I want to use?

React is a great start and pretty user friendly, Flutter offers a lot of integration to Google's services, Angular V2 has just recently came out, and Next.js offers something in between it all. One framework is special in this case, as it does something these other libraries/frameworks don't do. Svelte is truly unique as a framework, and is open to anyone to use. Lets delve into what makes it a special.

Svelte Breakdown

Svelte has a lot of key difference to the others. First of all Svelte is written in JS and TS. Now we need to explain what most of the other libraries/frameworks do in the form of sending info to the browser. You see, libraries like React will send runtimes and most if not all of the different libraries to the browser and let it settle all the information for it. That is not the case for Svelte, which compiles all of its code and then serves it to the client. This allows for faster performance and less bloat. Svelte also does everything in a single .svelte file.

The file structure is similar to this:

<script>
  import { v4 as uuidv4 } from 'uuid';
  import { createEventDispatcher } from 'svelte';
  import Card from './Card.svelte';
  import Button from './Button.svelte';
  import RatingSelect from './RatingSelect.svelte';
  let text = '';
  let rating = 10;
  let btnDisabled = true;
  let min = 10;
  let message;

  const dispatch = createEventDispatcher();

  const handleInput = () => {
    if (text.trim().length <= min) {
      message = `Text must be at least ${min} characters`;
      btnDisabled = true;
    } else {
      message = null;
      btnDisabled = false;
    }
  };

  const handleSelect = (e) => (rating = e.detail);

  const handleSubmit = () => {
    if (text.trim().length > min) {
      const newInfo = {
        id: uuidv4(),
        text,
        rating: +rating,
      };
      dispatch('add-idea', newInfo);
    }
  };
</script>

<Card>
  <header>
    <h2>Give us Ideas</h2>
  </header>
  <form on:submit|preventDefault={handleSubmit}>
    <RatingSelect on:rating-select={handleSelect} />
    <div class="input-group">
      <input
        type="text"
        on:input={handleInput}
        bind:value={text}
        placeholder="Tell us something interesting"
      />
      <Button disabled={btnDisabled} type="submit">Send</Button>
    </div>
    {#if message}
      <div class="message">
        {message}
      </div>
    {/if}
  </form>
</Card>

<style>
  header {
    max-width: 400px;
    margin: auto;
    text-align: center;
  }

  header h2 {
    font-size: 22px;
  }

  .input-group {
    display: flex;
    flex-direction: row;
    border: 1px solid #ccc;
    padding: 8px 10px;
    border-radius: 8px;
    margin-top: 15px;
  }

  input {
    flex-grow: 2;
    border: none;
    font-size: 16px;
  }

  input:focus {
    outline: none;
  }

  .message {
    padding-top: 10px;
    text-align: center;
    color: rebeccapurple;
  }
</style>
Enter fullscreen mode Exit fullscreen mode

This is an example of my own local demo with the help from this video: Traversy Media: Svelte Crash Course

Script Tag

To break this down, we will start with the script tag

<script>
  import { v4 as uuidv4 } from 'uuid';
  import { createEventDispatcher } from 'svelte';
  import Card from './Card.svelte';
  import Button from './Button.svelte';
  import RatingSelect from './RatingSelect.svelte';
  let text = '';
  let rating = 10;
  let btnDisabled = true;
  let min = 10;
  let message;

  const dispatch = createEventDispatcher();

  const handleInput = () => {
    if (text.trim().length <= min) {
      message = `Text must be at least ${min} characters`;
      btnDisabled = true;
    } else {
      message = null;
      btnDisabled = false;
    }
  };

  const handleSelect = (e) => (rating = e.detail);

  const handleSubmit = () => {
    if (text.trim().length > min) {
      const newInfo = {
        id: uuidv4(),
        text,
        rating: +rating,
      };
      dispatch('add-idea', newInfo);
    }
  };
</script>

Enter fullscreen mode Exit fullscreen mode

The script tag is where your standard code blocks will live. This is where the logic if provided to help display things on the screen or gives functionality to elements on the screen. Using the let keyword, we allow are variables to change depending on what we need them to change to, in the case of the code block we have a text field, a rating which will go up or down, a boolean for disabling a button, a min value, and a message declared. These are what we would consider dynamic variables. There is however another mounting state sytnax available to Svelte in the form of $:. When this is called, it allows the variable it is declaring to be dynamic in rendering based on what is provided. Here is an example of one; $: count = info.length;.
In this case count re-renders when info.length changes. Another quick block you see in the example above is this import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher();. This is a way to pass custom event triggers up to the most top parent component in Svelte and allows that parent to watch for changes to the actual element that is changing to determine what to do next.

HTML Element or Main tag

Next we come to the actual html elements that are used. This is similar to React where you build out the smaller components and fit them into bigger components. To do this, in the script tag you must import the component just as you do in a JSX or TSX folder. Then in the html element you would reference inside of a <main> tag. It is important that there is a main tag and usually that is the top most level of the project. After that its down the html rabbit hole of different tags that would be used. The best part, is that most the components don't need a parent div tag to start. Lets break down two examples:

<Card>
  <header>
    <h2>Give us Ideas</h2>
  </header>
  <form on:submit|preventDefault={handleSubmit}>
    <RatingSelect on:rating-select={handleSelect} />
    <div class="input-group">
      <input
        type="text"
        on:input={handleInput}
        bind:value={text}
        placeholder="Tell us something interesting"
      />
      <Button disabled={btnDisabled} type="submit">Send</Button>
    </div>
    {#if message}
      <div class="message">
        {message}
      </div>
    {/if}
  </form>
</Card>
Enter fullscreen mode Exit fullscreen mode

From the code above

<main class="container">
  <IdeaForm on:add-idea={addIdea} />
  <InfoStats {count} {average} />
  <FeedbackList {info} on:delete-feedback={deleteInfo} />
</main>
Enter fullscreen mode Exit fullscreen mode

From the App.svelte file in the demo

The second example is shown to be the top most part of the application, showing different tags inside a main tag. Those other tags are components from another file. Another good thing about svelte is there is not exporting of the html elements. If you look closely, there are some other syntax choices that stand out in the form of on:<event> and {#if}. on:<event> is a event listener tag similar to onClick for React. It will watch the element and dictate an action based on what is being watched. Example 2 has a listener for a delete custom function that is passed up to this top level. It will see the details of that event and then execute code that we wrote to delete the feedback. {#} is interesting as it is used to write conditional logic and iterative login into the html element itself. Example 1 has some conditional logic that renders a message if there is one to begin with. For the iterative (or {#each}), it takes a iterative object or count, and renders x amount of components based on the iterative logic. This is similar to how {example.map(...)} works for React to display elements on the page from an array of elements.

Style tag

<style>
  header {
    max-width: 400px;
    margin: auto;
    text-align: center;
  }

  header h2 {
    font-size: 22px;
  }

  .input-group {
    display: flex;
    flex-direction: row;
    border: 1px solid #ccc;
    padding: 8px 10px;
    border-radius: 8px;
    margin-top: 15px;
  }

  input {
    flex-grow: 2;
    border: none;
    font-size: 16px;
  }

  input:focus {
    outline: none;
  }

  .message {
    padding-top: 10px;
    text-align: center;
    color: rebeccapurple;
  }
</style>
Enter fullscreen mode Exit fullscreen mode

Finally we get onto the style tag, which is most of the css and other styling you will do to the page. There is not much to say for those that have made apps and used css styling, but it's crazy to think that you could do something like this. More often than not though if you are big into styling you would work with libraries such as Attractions, SMUI (Svelte MUI), and Skeleton to help the styling process.

Image description

Attraction Example

Conclusion

Svelte has been an interesting study to me. I have such a small understanding of front end development because of my time working with just React. While it's not that bad, I can say safely that we are in an age where React is not the only way to build apps. Svelte is very intuitive in my opinion, and offers a new and refreshing way to building web apps. The community is small, but the docs are very detailed, have a lot of great tutorials to get you started, and has a developer that is really passionate about giving the user and developer a more seamless transition from code to display.

Resources: Official Docs, SvelteKit Docs, Attractions, Wiki,

Top comments (0)