Make Svelte better
Logic blocks syntax
The current syntax used for logic blocks looks weird and hard to write and remember, especially for beginners.
{#if}
{:else if}
{:else}
{/if}
{#each}
{/each}
{#await}
{:then}
{/await}
{#key}
{/key}
{@html}
{@const}
{@debug}
Let’s use a simple and clean syntax like this example:
{@if}
{@else if}
{@else}
{@endif}
{@each}
{@endeach}
{@await}
{@then}
{@endawait}
{@key}
{@endkey}
{@html}
{@const}
{@debug}
$alias
We use the $
symbol when accessing a store value, and I think it will be confusing for beginners if we also use it in our alias names. Developers may confuse about differentiating an alias from a store name. You can name your aliases however you like, but the svelte maintainers prefer the $
prefix, so that will be what most developers use.
<script>
// Hmm, let's create a variable for our path:
const components = readable("/src/lib/components")
// Now, let's use it to import our component:
import MyComponent from "$components/MyComponent.svelte"
</script>
Let’s use the @
symbol instead:
<script>
import MyComponent from "@components/MyComponent.svelte"
</script>
This will indeed make Brittney so happy😄.
class
prop
Let’s say you want to create a prop to add custom classes to your component. Let’s see how we can do that.
MyComponent.svelte
:
<script>
export let class
</script>
<div {class} />
App.svelte
:
<script>
import MyComponent from "./MyComponent.svelte"
</script>
<MyComponent class="my-class" />
<style>
.my-class {
display: block;
}
</style>
The example above is a simple and clean way to add custom classes and styles to your component from a parent component. The problem is, that doesn’t work! To make it work, you need to change some stuff in MyComponent.svelte
:
<script>
export let className
export { className as class }
</script>
<div class={className} />
Now you can add your custom classes. But don’t get happy yet, because there is a catch. Your custom classes will only work if they are global, like in the old days when we had one big CSS file and were using it for everything. The problem is, Svelte doesn’t recognize the prop as a class
attribute. As a result, it thinks the .my-class
styles are not being used, so it removes them from the output. Fix it like this:
<div class="my-wrapper">
<MyComponent class="my-class" />
</div>
<style>
.my-wrapper :global(.my-class) {
display: block;
}
</style>
Using the :global
feature makes your styles global to your entire app. We add the my-wrapper
element to the scope that styles back into your component.
Comments
None of these examples work. Because the Svelte maintainers think we should carry around these existing problems in HTML, CSS, and JavaScript and that they don’t worth solving. You can’t also wrap an HTML attribute or a component prop inside a comment tag.
<!-- <div>
<!-- <div></div> -->
</div> -->
<div
<!-- class="" -->
></div>
<MyComponent
<!-- myProp="" -->
></MyComponent>
/* div {
/* display: block; */
} */
/* function doAThing() {
/* console.log() */
} */
CSS scope
A11Y
We need a feature to disable all A11Y warnings together, on the frontend and in the terminal. We may also need to disable them individually, so if there was an incorrect warning, we easily disable it.
Layouts
sveltekit#627
- You can’t pass data from a page up to its layout.
- You can’t fully treat layouts as a svelte component because they don’t support features like: named slots, slot fallbacks, optional slots and slot props.
Dynamic classes
There is no clean syntax to dynamically add classes.
Syntax 1
<div class:bg-brand={condition} />
- ❌ This isn’t a standard syntax because the classes should come after the equal sign.
- ❌ You can’t use multiple classes, and because of that, you need to introduce a new syntax to your codebase.
Syntax 2
<div class={condition ? "bg-brand rotate-45" : ""} />
<div class="{condition ? 'bg-brand rotate-45' : ''} text-white" />
- ✅ You can use multiple classes.
- ❌ Boilerplate.
Syntax 3
<div class="{condition && 'bg-brand rotate-45'} text-white" />
- ✅ You can use multiple classes.
- ✅ Clean and readable.
- ❌ You may get classes like
false
,null
, andundefined
as a result of a Falsy value.
What is the solution?
Use Syntax 3 and ignore adding classe like false
, null
and undefined
. Also, deprecate Syntax 1 in Svelte version 4, because it’s not gonna be useful anymore.
Port is already in use
Automatically change the port number if the current one is already in use.
Dynamic HTML tags
This feature is now available 👏.
<script>
let tag = 'div'
</script>
<svelte:element this={tag}>
...
</svelte:element>
Change the this
prop name to tag
, because what if we also want to bind the element to a variable? Example:
<script>
let tag = 'div'
let element
</script>
<svelte:element
this={tag}
bind:this={element}
>
...
</svelte:element>
It works, but it looks like we accidentally added the prop twice!
Docs
Documentation content and the design needs a rewrite and a redesign. There is a lot of content missing in the docs It’s the year 2022 and we don’t have a freaking Dark Mode! A proper way of accessing and searching content. Algolia sucks because it’s not accessible it some countries like Iran, so need to use a VPN to be able to use it!
Better error handling
It’s absolutely disgusting how Svelte handles errors! Basically, you don’t know what the hell is going on.
Internationalization
You can learn about how PHP and Wordpress do i18n from here:
- How to Translate With GetText PO and POT Files
- Wordpress: Internationalization
- Wordpress: How to Internationalize Your Plugin
Using JSON .json
files for i18n is a huge big mistake. We should use PO (.pot
, .po
, .mo
) files instead because they are a known standard for years for millions of developers and translators, and software when creating translation files. It’s not just the PHP ecosystem that uses this convention. Svelte can take the same solution and implement it. This will highly benefit everyone. Using JSON files is hard, unmaintainable, and tidies. You can easily use tools like PoEdit for translation with the power of the community’s previous translations, AI-like features, and by getting help from Google Translate. We also need to use syntaxes like __()
for wrapping the translatable strings because it is a known standard.