This post first appeared on www.mikenikles.com.
Photo by Aryan Singh on Unsplash
React was my go-to choice for many years
On October 14, 2015, I hosted the inaugural React Vancouver meetup. It was at a point were I had used React for the better part of the year and wanted to bring like-minded developers together.
React back then was, dare I say it, revolutionary in the web frontend world. Compared to the alternatives such as jQuery, Backbone.js or Angular 1.x, developing with React felt intuitive, refreshing and productive. Personally, the idea of isolated building blocks (aka components) really appealed to me as it naturally led to a structured, well organized and more maintainable code base.
Over the coming years, I kept a close eye on Angular 2.x+, Vue et al but none felt like a wortwhile choice to jump ship.
Then I learned about Svelte
I first learned about Svelte in mid 2018, almost a year before version 3.0 was released (see below). "Computer, build me an app." by Rich Harris is what got me hooked on Svelte.
If you're not familiar with Svelte (https://svelte.dev/), please go to the website and spend 5 minutes reading the intro.
Read it? Really? Excellent 👍
Once I watched the video, the main question in my mind was whether or not it's worth learning Svelte and starting to use it for new or even existing projects. In all fairness, Svelte impressed me but it still wasn't enough to embrace it fully.
Svelte 3.x
April 22, 2019 - Svelte 3: Rethinking reactivity was the blog post I had been waiting for.
Please take some time to read the blog post and watch the video - it's about spreadsheets but I promise it's fun 😉
Why was this such a big deal? For one, the Svelte team had been talking about version 3 quite a bit and I wanted to see it in action. On the other hand, Svelte and its promise excited me even more than React did when first I heard of it.
I mentored web developers at that time and had spent quite a bit of time bringing them up to speed on React. Things like JSX, CSS-in-JS, Redux, create-react-app, SSR and other concepts needed to be learned, understood and to a certain degree mastered in order to develop React apps.
None of that was necessary with Svelte.
<script>
let name = 'world';
</script>
<style>
h1 {
color: blue;
}
</style>
<h1>Hello {name}!</h1>
Simple enough? I agree. In fact, it is so simple I recommend it to my mentees who are new to web development.
Real quick, what's going on in that code?
The script
tag is where the component's logic lives.
The style
tag defines this component's CSS - none of this leaks outside the component, so we can safely use h1 and it only applies to this component. It's real CSS, not a Javascript object that pretends to be CSS or a string literal that pretends to be CSS.
At the bottom is the component's HTML. Use variables with {myVariable}
. Compared to React's JSX, Svelte allows you to use the correct HTML tags such as for
, class
instead of forHtml
and className
. See "Differencs In Attributes" in the React documentation for a list of all attributes that are not standard HTML.
Let's rebuild React examples
To give you an idea of what Svelte looks like compared to React, let's rebuild what's listed on https://reactjs.org/.
A Simple Component
See the code snippet above.
A Stateful Component
<script>
let seconds = 0;
setInterval(() => seconds += 1, 1000);
</script>
Seconds: {seconds}
React: 33 lines
Svelte: 6 lines
An Application
<script>
/* App.svelte */
import TodoList from './TodoList.svelte';
let items = [];
let text = '';
const handleSubmit = () => {
if (!text.length) {
return
}
const newItem = {
text,
id: Date.now(),
};
items = items.concat(newItem);
}
</script>
<div>
<h3>TODO</h3>
<TodoList {items} />
<form on:submit|preventDefault={handleSubmit}>
<label for="new-todo">
What needs to be done?
</label>
<input
id="new-todo"
bind:value={text}
/>
<button>
Add #{items.length + 1}
</button>
</form>
</div>
<script>
/* TodoList.svelte */
export let items = [];
</script>
<ul>
{#each items as item}
<li key={item.id}>{item.text}</li>
{/each}
</ul>
React: 66 lines
Svelte: 43 lines
A component Using External Plugins
<script>
const md = new window.remarkable.Remarkable();
let value = 'Hello, **world**!';
</script>
<svelte:head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/remarkable/2.0.0/remarkable.min.js"></script>
</svelte:head>
<div className="MarkdownEditor">
<h3>Input</h3>
<label htmlFor="markdown-content">
Enter some markdown
</label>
<textarea
id="markdown-content"
bind:value={value}
/>
<h3>Output</h3>
<div
className="content">
{@html md.render(value)}
</div>
</div>
React: 42 lines
Svelte: 24 lines
Less code = fewer bugs
Less code = better performance = better user experience
Less code = less maintenance = more time to develop features
What else do I like about Svelte?
Reactivity
Another powerful feature is reactive declarations. Let's start with an example:
<script>
let count = 0;
$: doubled = count * 2;
function handleClick() {
count += 1;
}
</script>
<button on:click={handleClick}>
Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
<p>{count} doubled is {doubled}</p>
Whenever you have variables that depend on other variables, declare them with $: myVariable = [code that references other variables]
. Above, whenever count changes, doubled gets recalculated automatically and the UI updates to reflect the new value.
Stores
In cases where state needs to be shared across components, Svelte provides the concept of stores. The tutorial explains stores well. No need to read lengthy tutorials - stores are that simple.
Derived stores
Often, one store depends on other stores. This is where Svelte provides derived()
to combine stores. See the tutorial for details.
Await as a logic block
Alright, this one is a quite elegant. Let's start with the code (interactive demo):
<script>
let githubRepoInfoPromise;
let repoName = 'mikenikles/ghost-v3-google-cloud-storage';
const loadRepoInfo = async () => {
const response = await fetch(`https://api.github.com/repos/${repoName}`);
if (response.status === 200) {
return await response.json();
} else {
throw new Error(response.statusText);
}
}
const handleClick = () => {
githubRepoInfoPromise = loadRepoInfo();
}
</script>
<input type="text" placeholder="user/repo" bind:value={repoName} />
<button on:click={handleClick}>
load Github repo info
</button>
{#await githubRepoInfoPromise}
<p>...loading</p>
{:then apiResponse}
<p>{apiResponse ? `${apiResponse.full_name} is written in ${apiResponse.language}` : ''}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{/await}
See the #await
block in the HTML? In a real-world application, you'd have a Loading component, an error component and the actual component to render the API response in this case. Try to enter an invalid repo name in the text box to trigger the error case.
"But wait, what about..."
open source components?
The main response I get when I introduce Svelte to someone is "but what about the ecosystem, components, tutorials, tools, etc?"
Yes, there are nowhere near as many open source Svelte components as there are components for React. Having said that though, how often do you take an open source React component and integrate it without any issues or unnecessary overhead? I'd argue many of us in the Javascript community have become too reliant on npm install ...
to piece together a web application. Often building your own components, especially in Svelte, leads to less time spent overall. I have no data to proof that, it's base on my personal experience.
Related though, there is a growing list of Svelte components for anyone who sees comfort in reusing open source components.
finding a job?
Plenty of opportunities, see https://sveltejobs.dev/. Apple's Fraud Engineering team is looking for a Svelte developer (as of December 2019).
Also remember, the competition is much smaller compared to applying for a job that requires React, Vue, Angular, etc.
And then, there's Sapper to deploy Svelte apps
Developing an app is only a piece of the full cake - the app also needs to be deployed. For this, the Svelte team provides Sapper. That's an entire post in itself, so for now please have a look at the website for details.
Conclusion
That brings me to the second part of this blog's title, "why others will follow." Every day, new web developers start their journey and the first thing many hit is an uncertainty of what to learn first. I say the future is about simplicity, quick time to market and I can't think of anything simpler and quicker than this:
<script>
let name = 'world';
</script>
<style>
h1 {
color: blue;
}
</style>
<h1>Hello {name}!</h1>
Do hit me up on Twitter @mikenikles with your feedback.
👋
Top comments (41)
I always find it funny when I see a post about comparing frameworks or languages
and they would start comparing
whateverlanguage1
withwhateverlanguage2
, to convince others whywhateverlanguage2
is better thanwhateverlanguage1
, using arguments, likeI mean, X|Y lines of code using what methods?
Line breaks after and before every brackets for example?
Each variable in new line?
Over engineering with whateverlanguage1|2, using some extreme functions?
Of course you can create a counter in a few lines, OR, you can do it in 100 lines too in every single language, if you are over engineering it.
My point is: use whatever language/framework you want to use, which you like better, which you're already used to, which you think is the best for a given task. Don't ever start compressions like
whateverlanguage2
is 3 lines less thanwhateverlanguage1
. That alone doesn't make one better at all.Hi Patrik,
I agree with that. Lines of code should not be a reason to pick one framework over another. That wasn't the key message of my post. I kept the formatting of the Svelte components as close to the way React formats their code on the homepage for a 1:1 comparison. As I outlined below the comparisons, less code means fewer bugs, better performance, etc.
The fact that Svelte is generally smaller than React is a nice side benefit to me, but by no means the main reason I advocate for it.
As someone not versed in either framework, the Svelte code is not just shorter but also looks much easier. The two first examples are totally self explaining to any developer.
Your article makes me really consider picking up some front end skills.
As a long time Front End Engineer, who's been through many frameworks, Svelte is a breath of fresh air and actually makes building components, etc. a nice experience. It also has accessibility out of the box, and feels closer to vanilla JS than other libraries/frameworks.
Even though I like svelte, I quite agree with the line of codes metric being not a good metric to measure svelte's success over other framework.
I think what good svelte brought was the ease of use and optimization it brought to the fold.
It'll be cooler if svelte's module can be interoperated with other framework or plain js that does other type of job (e.g. headless state management, event sourcing, API call abstractions). Being able to be mix and matched ala functional programming modules / lego will punch svelte's value upward.
I think the point about smaller code performing better is slightly moot in these examples. Remember that it is the respective compilers (svelte in general, react with jsx) that are ultimately responsible for the performance of the code that runs in the browser (ignoring the overhead of the framework in react's case). The svelte compiler will probably output a lot more code than what was input.
I am aware of svelte's benchmarks btw, I'm just highlighting the fact that you don't know it'll perform faster just because YOU'VE written less code ;)
That is true, and Svelte might even output less code even if you had written MORE code. This is the true power of using a compiler like Svelte - any optimizations it comes up with as it develops, will benefit you even if you never write a new line of code.
Really?
on:submit|preventDefault
Is this a new incredibly ugly way to define inline JS? Is that a...pipe in there?
htmlFor
Never seen that HTML attr before 🤔
Hi Avon,
Thanks for your feedback.
The
on:submit|preventDefault
syntax is optional. We could use the regularevent.preventDefault();
call in thehandleSubmit()
function to keep the HTML cleaner.In case of the
htmlFor
, thanks for pointing that out. I copied the initial source code from the React website to make sure I don't miss any feature in the Svelte version. I've updated the blog post and the interactive demo to usefor
.Good to know; appreciate you clarifying!
More accurate critic would be: svelte is not html at all.
Rich Harris introduce this language as htmlx github.com/htmlx-org/HTMLx.
If it has different parser from html, it is a different language.
I've been thinking it might be worthwhile to use Svelte within DEV in addition to Preact. We choose Preact over React because we want to be minimal with our underlying bundles. The small footprint of Svelte in this regard makes me feel like we can offer up both underlying libraries for our developers to choose from based on preference for different parts of the site without going over our bytes budget.
I like everything I'm seeing about Svelte and feel like we can adopt it without throwing out our other approaches.
I think that's one of the very cool aspects of Svelte. It doesn't have a ton of baggage with it ( loading a whole lib before you can use it) and you can just sprinkle it in on top of other frameworks / languages and feel confident that it will not interfere or add too much pageweight. It's very "subversive" in that way.
Right, Svelte fits in well in terms of its bundle sizes.
I haven't mixed (P)react & Svelte components on the same page, but there is an example at github.com/Rich-Harris/react-svelte with Svelte 2.x. Likely a good starting point for an experiment.
As a beginner web dev I recently discovered React and built a few bits and pieces in it and I find it fairly intuitive. That said, I also discovered Svelt and am totally swept with it. It's so intuitively simple. My favourite thing about it is that any React app I've made (always with
create-react-app
) just feels huge. Even the base project just feels like a monster, whereas my Svelte app feels tiny and simple. I'm looking forward to developing more in Svelte soon!That’s because CRA is a bundle with lot of stuff that you will never understand just by studying React.
React Itself it’s just a package to import.
This reminds me of Vue. When I tried Vue after React it seemed very simple
Thank you for a nice article. Really shows up advantages of Svelte.
Svelte is great for small apps, widgets, forms, perhaps medium sized projects as well.
However, to be used in larger apps, I would like to see routing and state solutions built for Svelte, kinda Vue has, devtools to debug the code. While Svelte is not providing anything alike it will be used as a side, great tool to cover quicck and simple needs. Other way it is pretty hard to convince managers to use it for company's development needs.
Anyway it is a fresh tech in the FED tooling and we are all really looking forward for Svelte to grow and mature in 2020.
Ho ho ho :)
how often do you take an open source React component and integrate it without any issues or unnecessary overhead
. Very often, I don't know what you have been working with lately...I really don't understand how this "downside" is leaned as a positive aspect in your article.
too reliant on npm install ...
that's, like, one of the most important upsides of modern web development: there are a lot of code out there that one can easily import and use it on its project.Often building your own components, especially in Svelte, leads to less time spent overall.
It would be really nice if you provided one real-life example of this, because that phrase doesn't make sense in my head for most of the web-development that I do (landing pages, ecommerce stores...), specially when using something like MaterialUI.I don't like Svelte, I may take it for its allegedly perfomance benefits, but explaining why one needs to add a
$
in the code when it "depends" on something seems way harder than explaining about renders and the hole component as a function. I still didn't grasp its "simplicity", but I value innovation and support Svelte, still not seeing why would anybody leave React as of now, it's a way different momentum than the AngularJS migration.Hi Luciano,
Thank you for taking the time to provide your feedback.
In a scenario where a web app's design is based on MaterialUI, I agree that using an existing component library is the best and most efficient approach. For Svelte, there's sveltematerialui.com/ as a starting point.
The use cases I encounter most often is where web apps are designed by an in-house design team and the web developers develop according to the design specifications. While there are many open source calendar components for example, they often provide features that are not needed. In my experience, this can add complexity, unnecessarily increase JS bundle and CSS file sizes and make it more complicated to add features that are unique to a business. On the flip side, developing custom components requires more testing (e.g. cross browser compatibility) so it is a bit of a balancing act on a case by case situation I'd say.
As for my comment on being too reliant on
npm install
: Imagine a situation with 15 frontend developers working in 3 teams. What I think tends to happen is that developers' first instinct is to search NPM for a component, install it and use it. Each component often comes with its own dependencies (both direct & transient) and sometimes developers on different teams add different npm packages to solve similar needs. This slows down the build pipeline & potentially increases the final bundle size. With good internal team communication and a share component library, this kind of duplication should be kept under control.As with many things in tech, whether Svelte is the right decision or not depends on many factors. In my case, so far, I've had a good experience.
Have you learn and dive into VueJS?
You said that you have looked for Angular 2 and VueJS.
I think if you have learnt about VueJS, even for the simple "Getting Started" part in its docs, you will recognize the Svelte almost in similar in style with VueJS, the Single File Component (SFC) style.
As you said have looked for Vue, I expect that you would say something like "Svelte is VueJS with ReactJS combined plus blablabla"
😁
Because it really is.
The separation of html, script and style, is what the SFC doing (template, script, style (scoped or global)).
The 'on:click' syntax, what the different with 'v-on:click' (or the shorten version '@click') in VueJS.
But the '{handleClick}' syntax is React way.
So, the 'on:click={handleClick}' is the VueJS combined with ReactJS.
Oh, I almost forget, the "store" for global state is also similar to Vuex (State Management for VueJS), ofcourse with different code to write and concept.
But anyway, nice post.
Thanks for sharing.
I almost consider using Svelte, when my friend and boss tell me about it.
But, we don't use it already.
And I didn't have yet plan to jump into company which using it.
😅
P.S: I still wandering the future where, people don't need to learn new (and always new) way to write Front End codes. The future where there are no Angular, VueJS, ReactJS, Svelte or whatever-will-be.
Just HTML, CSS/SASS, and JS.
But in a way that can harness the power of those framework, i.e: the reactivity, modular component, data binding, style binding, etc.
And people will stick to it for decades.
I don't know why, but I always think that the new framework is somehow better than previous one but always keep introducing new term, syntax, concept.
In my opinion, it looks so selfish improvement.
"on:click" (Svelte)
"v-on:click" (VueJS)
"@click" (VueJS)
Why don't we just stick with html syntax "onclick".
I know perhaps it has something to do with the parser for each framework.
But guys who develop those framework are genious. They would have found the way.
If they want to keep it that way.
But yeah, here the result.
Another syntax to learn.
FYI your "A Component using External Modules" seems to have an error in the Svelte repl: svelte.dev/repl/28f4b2e36e4244b8b2...
It's showing:
Cannot read property 'Remarkable' of undefined
Nice catch Andrew, it looks like there was a race condition where the external JS file didn't provide its global
window.remarkable
object quickly enough.That's fixed now - thank you for letting me know.
Thanks for responding and getting it to work! I learned more about Svelte looking at how you fixed it.
As a brand new developer I'm so glad Svelte is available. It's helped me to create projects that work while I learn the fundamentals of JavaScript. The ability to declare variables and functions and use them directly in the markup is the first thing I found attractive. I know it's not all that different than template literals but it's been very helpful.
The other thing I find helpful for learning is that components are separated into script, markup, and style sections. It's very easy to keep track of what's happening inside of a component. That and safe component scope has really helped.
Finally, and this was a big deal, I was able to finish a simple teleprompter app within a couple of weeks and upload the contents of the build directory to a plain-old Apache web server and everything worked. I didn't have to learn how to deploy, didn't have to push anything to github etc.
I'm sure I'll explore other frameworks but I have to say Svelte has been a fantastic way to learn.