I've been building something with Svelte 3 for about 6 months now.
- As should be clear in the article, it's very easy to pick up. In the first couple of weeks I got compiler errors, and kept having to look at how props and binding worked in the tutorial, but now I just make components without having to really think about Svelte.
- TS support is on the way (yaay)
- I'd like to know more about server-side rendering on Lambda - ie, Sapper currently wants to use something persistent like Express, but that really shouldn't be necessary.
I've used Svelte to generate static HTML, it's pretty great at it.
If you pass generate: 'ssr' to the compile function https://svelte.dev/docs#svelte_compile you get JS that can be used to generate static HTML in a Lambda or anywhere else
Hah brill. It might just be the tutorials, which seem focused on using express or something with express-like middleware. I'll do some further investigation. Thanks.
This looks much more germane to the Web than the other frameworks du jour. Will be interesting to see how it develops, but this was a pretty interesting look at how it works.
JQuery was a completely different way of looking at things with a huge advantage. It got popular and became the go-to tool of the day.
Backbone and Angular were a completely different way of looking at things with a huge advantage. They got popular and became the go-to tool of the day.
React was a completely different way of looking at things with a huge advantage. It got popular and became the go-to tool of the day.
Svelte is a completely different way of looking at things with a huge advantage.
Even though these are compile/build time requirements, their size ends up slowing down CI/CD process.
Our ondemand cloud build servers download the code, restore nuget packages and download node modules. Most of the build time is spent downloading. Compiling generally takes an order of magnitude less time compared to those 2 steps.
This especially effects scenarios where end-to-end testing can only be done in a staging environment due to complexity of the product.
Sounds like you need some caching. I have three large production svelte projects and the entire checkout and npm install (Cache then update) process takes three seconds on CircleCI.
It can matter though; fwiw. I love Rust, but my "node_modules" in Rust is absolutely huge. Not a problem on Desktop, but because I am full-time Rust these days my next laptops have to have lots of storage. Gone are the days where I can have a small SSD in my laptop.
Fwiw though, even a 250MB node_modules would pale in comparison to my Rust version lol.
Keats is correct - I figured this is a JS discussion thread so rather than say my target folder, I'd use "node_modules" for familiarity. I should have probably explained that. A bit of verboseness would have saved more verbose comments haha.
The project I'm working on with only a couple web components using Angular already exceeded 400MB node_modules folder. Web development sometimes freak me out.
I loved Svelte a few years back and still think it's a nice framework with cool ideas. However, a big issue for me using it at a company is that testing (especially unit testing) seems to be an afterthought. This has made it a non-starter for using it with multiple teams working on same code base. Maybe it's changed with Svelte 3 but a library I wrote for it wasn't clear how to test.
JS libraries sometimes take a non-presciptive approach of "test however you want!", But roll your own testing for a UI framework really limits adoption and enthusiasm at larger companies.
Honestly, the biggest blocker to us having a 'blessed' story around testing isn't figuring out how to test (which is relatively straightforward), it's figuring out what to test. Do you really need to test that `<p>Hello {name}!</p>` results in `<p>Hello world!</p>` if `name = world`? Because then you're really just testing that the framework itself isn't buggy, rather than anything to do with your app.
Which isn't to dismiss the concern — just to offer an explanation as to why it hasn't been our top priority so far.
> "Because then you're really just testing that the framework itself isn't buggy"
Not in all cases, I maintain some component libraries (mostly React, but a Svelte one too) and ensuring a standard component interface is pretty valuable imho. Enzyme as an example lets you test React components, props, state, etc in isolation but is not very prescriptive about what you 'should' test.
React at least had ReactTestUtils 'officially' and then recommended ReactTestingLibrary & Enzyme as the ecosystem matured: https://reactjs.org/docs/test-utils.html
Angular really shines here, I feel. I really like protractor, and you can integrate it really easy with puppeteer (via expect-puppeteer or karma-chrome-launder with the option headless)
$$invalidate('items', items = items.filter(i => i !== item));
So this invalidates the whole array, right? Would this then re-render the whole array, i.e., remove and recreate all DOM nodes? And if so, does Svelte support more fine-grained ways to update arrays?
The TL;DR is that Svelte overpromises. They can't possibly write code for every transformation combination as code size would grow exponentially (I'm not completely sure, but I think predicting transforms would involve the halting problem).
I guess whether a structural comparison (VDOM) or a value comparison (Svelte) is more efficient really depends on the concrete use-case.
For example, even changing a single value in a big list requires the whole VDOM to be recreated, but should be very efficient in Svelte as it can directly modify the specific DOM node. On the other hand, as pointed out in the article you linked, if changing a value affects a large part of the DOM, but does not actually change that much, then value-comparing frameworks (e.g. Svelte) probably do a lot of unnecessary work compared to VDOM-based approaches (intuitively I would think that this case does not occur that often).
You don't have to recreate the entire vdom if only one part changes. You need only recreate that component and its children (something like React's PureComponent or shouldComponentUpdate optimizations can prevent the worst cases without too much trouble).
Changing branches in a component is extremely common in code I write (very large business application with lots of rules).
Another important optimization is caching and re-using DOM nodes. With a vdom, you know exactly which properties and attributes differ from the default node. To reuse a node you need only update these properties to their new values or restore their original values. Without that tracking, it would be computationally cheaper to just create a new node.
One important example of this is our use of flyweight scroller patterns in lists. The content of the sub-tree changes, but most of the sub-components stay the same, so a vdom could keep most of the dom nodes around.
A Svelte component is mutable & manages the related DOM elements which are also mutable. In the conditional, the tree is re-rendered.
Would React's diff algorithm be able to recycle the `<p>surgical</p>` DOM Node? How much more performant would detaching & reattaching `<p>surgical</p>` be than recreating `<p>surgical</p>`?
Assuming the `<p>surgical</p>` can be recycled, the use case having the largest effect is a large inner tree being wrapped/unwrapped; where the inner tree would simply be moved instead of recreated.
In Svelte, this can be optimized by using a subcomponent, as seen in the repl example. You can examine the compiled js.
I believe React recycles DOM nodes based on type (they decide some DOM nodes are faster to recreate instead of reuse depending on the circumstances)
I may be wrong, but I believe hyperapp recycles both the physical DOM node and the attached vdom node together (IIRC, they mark reused vdom nodes as "recycled" instead of directly comparing objects so they don't have to construct as many new vdom objects).
Preact kinda cheats here because they diff against the DOM directly.
React is very far from the fastest vdom. It notably suffers from needing to work with non-DOM back-ends where a particular heuristic that is good in the DOM may either be useless or (worse) actively degrade performance. Preact, Snabbdom, or Inferno would probably be better points of comparison to Svelte's approach as they are much more optimized for the web.
DOM nodes can actually be recycled relatively easily. Cache the nodes by type then by class. Most recycled nodes would be a 100% match based on those two alone. If type and class match, then you have a super-high probability of dealing with old nodes for the same object, so few modifications are required. Most nodes without classes tend to have no attributes changed (<div>, <p>, etc) so they will match as well. Store those nodes with their vdom attached and you will have a record of what has been modified so patching is fast.
This optimization exists in some vdom implementations and would make the case in question much faster. There also seems to be an implication that the diffing algorithm will bloat. If you look at React, the diffing algorithm is a very small part of the codebase.
This is hardly just an academic optimization though. It is the key to reducing overhead on long lists. With long lists of complex objects, you cannot rely on patching text values because there will undoubtedly be actual DOM differences. Rather than dooming the entire list to poor performance, you can recycle those nodes and retain most of the performance of a flyweight scroller where nodes are all identical.
Either I have completely misunderstood you or you are simply wrong. It looks like you are implying that vdom is magical solution to long lists and svelte should have problem here. While in real world we have this: https://svelte.dev/repl/f78ddd84a1a540a9a40512df39ef751b?ver...
Like most other scrollers, the svelte one tries to only show the elements on screen plus a couple above and below to keep up the illusion. The Google article makes it very clear that top performance requires re-using DOM nodes.
In that very simplistic example, there are only 4 nodes to each list, so creating and destroying them doesn't matter. I have a scroller in a business app where each item has a few hundred DOM nodes. Create and destroy them constantly and you'll definitely notice on a desktop and performance will crawl on a mobile device.
Instead, you want to save those DOM nodes in a cache and re-use them. In order to do this though, you must know what parts are default and what parts have been modified by their previous user. A vdom does this automatically, but the cost for Svelte to calculate which of the hundreds of properties have changed is too big, so they just throw it away and make another.
An even better optimization would be where each list item has the same node structure and only text or images change. I believe Svelte can handle this case. Unfortunately a lot of lists are slightly irregular in real-world applications. I work with these kinds of lists a lot and a vdom keeps it smoother than all the other libraries we've looked at.
Imagine you add a few attributes, some properties, and a couple event listeners to a node. In order to reuse the node, you have to reset it to factory settings.
How would Svelte know what things had been changed when looking at a node saved in a cache?
If it has to check every property, the cost to check will exceed the cost to create new. If it saves a list of changes, it's essentially created a vdom anyway.
Thank you for explaining that to me. It is good to know what technology to use if I will meet this specific case. So far all projects I have worked on can be implemented both with React and Svelte :)
Last time I tried keeping a collection of simple DOM nodes to "recycle" my perf tests showed it was slower than just creating new nodes. So I wouldn't necessarily consider this an optimisation, although memory use might be better.
It depends on how you recycle them I guess. One of Inferno's biggest optimizations (according to its creator) is the reuse of DOM nodes and vdom fragments. To my knowledge, it's still the fastest vdom implementation around.
When discussing structural changes, it seems like lifting constant fragments a compile time wasn't discussed. There's a Babel React optimizer to do exactly this. Lift those to their own functions. Since those functions don't take any props or state, their values are cached almost indefinitely.
Svelte author here. There's a couple of things to note:
- as Glench mentioned, it's not destroying and recreating stuff unnecessarily. By default it will create or destroy blocks at the end of the `each`, if the length of the array has changed. If you use a `key` then it will diff the input (as opposed to the output) and move elements around accordingly.
- `$$invalidate` is just an implementation detail, and is subject to change. There a couple of directions in which we plan to do so. One is to use bitmask-based change tracking, which would allow us to generate more compact code resulting in faster change checks (e.g. `changed & 7` instead of `changed.foo || changed.bar || changed.baz` when updating the view). Another is to track which nested properties of an object or array have changed — at the moment, `items[i] = item` invalidates all of `items`, but it would be great if we had a way to invalidate `items[i]` instead.
This looks nice. I'm not a framework guy (more on that in a second) but they at least seem to be heading in the direction of letting me get work done without forcing me to do it their way.
That said; first it was Backbone which wasn't terrible but kinda clunky in my opinion. But then Angular came along and everybody rushed over to that pasture. But then React came along and everybody rushed over to that pasture. Now Vue is appearing to be greener than the others. Is Svelte where everyone will go next?
My point is this: if all these frameworks were so great, why do we keep running to the latest new one? I actually heard a contractor say the other day, "five years ago everybody wanted Ember developers and now everybody wants React developers. I even have those old Ember clients coming back asking for developers to rewrite the Ember projects in React."
JSX is JavaScript. I do not have to learn a new language to iterate over an array. I can interact with it using whatever JS libraries I prefer. JSX components are functions or classes which are trivially composable. I can type functions and classes with typescript unlike string templates.
> I can interact with it using whatever JS libraries I prefer.
Could you give an example with JSX where templating will not cut?
> JSX components are functions or classes which are trivially composable.
This is framework's feature IMHO not language's.
> I can type functions and classes with typescript unlike string templates.
Situation where types are important in other frameworks is JS part not templates part. Could you give an example where typing is import purely in component's return value?
> Situation where types are important in other frameworks is JS part not templates part. Could you give an example where typing is import purely in component's return value?
You will lose type-safety when composing components in template-based frameworks. It is jsx part where types are most important. Instead of getting runtime errors because you passed wrong props you get instant feedback from tsserver and compile error.
JSX is decidedly not JavaScript, it is an extension to JavaScript.
> I do not have to learn a new language to iterate over an array.
Since you have to use map() and can't use a simple for-loop, not sure how knowing the language itself helps or not. Either way, loops and conditional are really the basics, you pick it up in a day or two for any template syntax.
> I can interact with it using whatever JS libraries I prefer.
Fair enough, but this prevents many optimizations because the render method can produce virtually anything.
> JSX components are functions or classes which are trivially composable.
This doesn't mean something else isn't as equally composable. Components are composable, doesn't mean they have to be classes or functions.
> I can type functions and classes with typescript unlike string templates.
What does this have to do with JSX ? I guess this is more valid claim for TSX. In any case, since svelte is a compiler, it should be possible to type-check components as well. And it doesn't even depend on typescript, so you can get the same static checks with vanilla javascript.
> JSX is decidedly not JavaScript, it is an extension to JavaScript.
No, JSX is JavaScript. You can write it in function calls or JSX, it's just syntactic sugar.
> Fair enough, but this prevents many optimizations because the render method can produce virtually anything.
No, using a library doesn't mean the function used from the library isn't pure. Yes it could have side-effects, but the point is you aren't restricted. You can use pure functions or anything else.
> In any case, since svelte is a compiler, it should be possible to type-check components as well.
Yes. But it doesn't, and you get it for free because TSX is just TypeScript. If wishes and buts were candy and nuts...
I don't think the claim that that is his opinion is a big claim, and while it's possible that he is misrepresenting his opinion the fact they he claimed the opinion on HN with no obvious benefit from misrepresentation is itself fairly strong evidence that it is his opinion.
tl;dr watch this fantastic intro to svelte talk by it's creator: https://www.youtube.com/watch?v=AdNJ3fydeao , it covers some of the growing pains of React that svelte addresses.
While it might look like the frontend is going around in circles, there are major & minor differences between the technologies, and they have each introduced novel (to JS at least) things... Off the top of my head (this timeline might not be right but it's how I went through it at least):
- Backbone got you away from jquery spaghetti, helped you actually manage your data & models. Often paired with Marionette to handle views (if you squint this is the precursor to components) and bring some order in that part of the app.
- Angular bundles backbone's data handling (services), marionette's orderly view separation (views, directives), but they made a fatal mistake in the apply/digest cycle and maybe encouraging a bit too much complexity. Angular is everything bundled together, with consistent usage/documentation/semantics, a familiar programming pattern (MVC), and a large corporate sponsor in Google it caught on like wildfire.
- Knockout sees Angular's MVC, laments it's complexity and focuses on MVVM -- simple binding of a model and a relatively simple reactive-where-necessary controller
- React comes along and suggests an even simpler world where the only first class citizen is components and everything else comes separate (this isn't necessarily new, there is an article out there comparing it to COM subsystems for windows). React is almost always used with react-router and some flux-pattern supporting data management lib -- these are also departures from how angular, backbone and knockout structured in-application communication (backbone was pure event bus, angular had the usual MVC methods, knockout was just callbacks -- if you have a handle to an observable when you change it things reload).
- Vue sees the complexity that React grew to (case in point: shouldComponentUpdate) and devises a much simpler subset along with a new way to handle reactivity -- using the `data` method of a vue component. Vue made a lot of decisions that helped it stay simple and small yet very productive and this is in large part thanks to React existing before hand.
- Svelte comes on the scene and realizes that truly optimal rendering could be achieved by just compiling away the excess and eschewing the virtual dom all together in most cases. No need to track all the structure if you compile the code with the updates necessary. Don't quote me on this but I think a whole host of things influenced this project -- smarter compilers, better type systems, the ideas around zero cost abstractions & doing more work at build time.
- Ember (formerly SproutCore) is actually an anomaly because it tries it's best to be both angular like (so large, and usable by large teams) and keeping up with the tech as it evolves (see: Glimmer, Octane). Ember also has some innovations, like Glimmer's VM-based approach -- turns out you can just ship binary data representing how to draw your components to the browser and skip a bunch of JS parsing, if you bring your own virtual machine that is optimized to draw the components.
As all this moves forward, there are ecosystem pieces like typescript that have gained tons of steam and changed how people are writing JS code these days.
This is literally the first time anyone has ever put together a cogent argument for why the framework du jour exists. Thank you!
I still personally feel like I can usually get more done with pure Javascript but, as I said in my original post, at least they appear to be headed in a better direction. I did a project in Vue last year and it didn't entirely suck. Unlike the nightmare that was an Angular project I did two years ago.
Oh definitely -- when you can get stuff done with pure javascript it's beautiful -- but once you notice yourself doing too much, it's time to pick one of these small frameworks.
BTW, you should check out Mithril[0], it's my current favorite, it's very small and self-contained yet very complete. It's got a slow, cautious moving community, and just enough of what you need and virtually nothing you don't -- very easy to use without bundling at all.
Also, the web components spec[1] is on the horizon and once it lands (and most frameworks support some mode where they spit out web components) we're going to get interop for free.
Also pro tip if you're going to start a new project these days and you need to get in the whole bundling swamp, use parcel. It's amazing, almost always zero config or close to it, and just works[2].
Commenting on my own comment, but Polymer[0] also deserves some love! v3 looks really amazing ergonomics wise, and it's the most web-standards friendly. The early demos of polymer (some showing being able to just drop a <google-map/> on your plain HTML page) really were mind-blowing. Also, it's actually in use on a bunch of google properties, like Youtube (you can actually see on some of the older pages that some URLs have a some use_polymer query parameter that turns it on/off).
Polymer is really interesting because it represents a kind of return to the early web but with all the new-web thinking -- just drop some custom component on your page (so only needing to think in HTML) and you're good to go.
In an earlier comment, you said you weren't a "framework guy".
If you were you would have heard this cogent argument dozens of times already as it's fairly common knowledge to people who are into frameworks.
Consider trying to understand why frameworks are created before using them. Understanding the motivations behind a framework will help you navigate the api easily and could change your opinion about whatever frustrates you.
I've used every one of the frameworks that I mentioned with the exception of Svelte, and am surrounded by framework users. Not a single one has ever made that argument. It's always, "Look at this new shiny framework, we must use it!"
And all of those frameworks were great right up until the point that my client or company had a product requirement that the framework designers hadn't though of and then, suddenly, the framework was working against me instead of for me.
I'd also consider myself not a "framework guy" -- Spring is not my favorite, I pick flask/sinatra over rails/django, servant over yesod, vue + vue-router over ember (these days) etc.
Maybe the distinction is that it really matters which framework, and how it's put together, and how much you have to commit to use any of it.
I think the commenter's question was really more about the diaspora of these tools and why they all exist -- svelte is pretty decidedly not a framework (in fact I don't even think you can make it one, AFAIK there isn't like a "svelte data"). IMO the only full blown frontend frameworks are Ember, Angular and react/vue + react/vue-router + flux-y pattern data store.
For reference, the blog post that you're thinking of is "The More Things Change" [0], which compares React + Flux to a Win32 `WndProc` function. Original HN comments for that thread are at [1].
> I actually heard a contractor say the other day, "five years ago everybody wanted Ember developers and now everybody wants React developers. I even have those old Ember clients coming back asking for developers to rewrite the Ember projects in React."
React came out a little over 6 years ago and Khan Academy started using it soon after. We haven't been itching to switch and, from what I've seen, there are _still_ a lot of people adopting it. Its model is working pretty well, generally.
I like that Svelte is taking a different approach. To move away from React will take something that's as big a switch as the jQuery+Backbone switch was when React came out.
I like reading scientific papers and most examples sections provide rich and intricate outlines of real-life use-cases where the idea can be experimented against. These examples usually involve quite complicated scenarios that "put the idea to the test".
One that I recently read involved a solution to the "Challenge Problem" [1] (simulating the movement of a rover) which involves lots of interesting properties and allows one's idea or framework (or whatever) to really battle test the grounds with reality.
On the web however it's different... we're somehow stuck with todo-lists.
Todo apps are used as front-end examples for the same reason the factorial function is used to explain recursion: it's simple, it's intuitive, but it exercises what you need without dragging in a lot of incidental complexity.
To demo or teach a front-end framework, you need to show:
1. How data gets rendered to the DOM
2. How collections are handled
3. How events are registered and handled
4. How the DOM is updated when data are changed
5. How form inputs are represented
The easiest thing to do is to show an array getting rendered as a list, then add click handlers which change the list somehow, which naturally segues into showing how the DOM is changed. Adding new items or deleting items also answer important questions about how exactly collections of data are mapped to collections of elements and how updates are happened. Finally, no demo of a front-end framework can be considered complete unless it addresses how form input elements work; adding functionality to add a new item or update the text of an existing item is an obvious way to demonstrate this.
I disagree. Those things are already available in pure library-less and framework-less code. What frameworks should provide is a solution at scale (i) as complexity increases, (ii) whether code is more maintainable or not and (iii) also I guess how easy it is to "fix" as bugs are discovered.
A todo-list gives you pretty much 0 insight into almost any of these facets. Let's be honest here, it's a "hello world" cheap demo to quickly showcase: "here's how my new framework works" and you can quickly understand it.
But you have no way of understanding whether those framework decisions actually work at scale. More complex examples are a good thing, not a bad thing :)
To be fair, the Svelte bundle.js that you would actually serve to a browser is only 2.3kb. The 25mb is what the dev's computer has to store in its node_modules.
"Another nice thing: the node_modules folder for this Hello World Svelte app totals only 29MB and 242 packages. Compare that to 204MB and 1017 packages for a fresh Create React App project."
Omitting html, head, and body tags is allowed by HTML specs, and the script tag's default type is "text/javascript". So it could be further simplified to:
FWIW, that React demo should not be used as a network perf comparison in any way:
- It's using an ancient version of React (0.13.3)
- It's a debug build of "React with addons", not a minified prod build
- It appears to include `JSXTransformer.js` as a separate script to handle in-browser JSX compilation
If you were to redo this using a modern version of React and a standard CRA build, I guarantee it would be _much_ smaller.
edit
Just for kicks, I did a quick search and dug up a pre-existing React "TodoMVC" app based on CRA ( https://github.com/ChrisWiles/React-todoMVC ). It's 3 years old, but it was trivial to bump the requirements up to the latest versions of React and react-scripts.
From there, running `yarn build` says that:
File sizes after gzip:
39.22 KB build\static\js\2.3ec0f98b.chunk.js
2.14 KB build\static\js\main.4514f0a8.chunk.js
1.73 KB build\static\css\2.bc2ff3bb.chunk.css
782 B build\static\js\runtime~main.0ff4d30b.js
Looks like Preact comes in at 6K (compresses to 4.7K). That's pretty interesting when you realize that Preact generally about as fast or faster than Svelte in a lot of benchmarks.
That said, I don't know that 6K vs 40K is particularly significant. For small apps, it disappears into the noise compared to ads, images, video, trackers, etc. For large apps, the framework starts to make less and less of a total percentage of the total app and often slides into insignificance on that side as well.
We need someone to take Svelte on a test drive for something more complex than a to-do list. I'm assuming the results will be favorable to svelte, but please blog after said exercise. The un-ending list of blogs and tutorials on to-do lists with svelte are certainly plentiful, repetitive, and not particularly convincing
While I'm still in the wait-and-see stage of evaluating Svelte, Pinafore [1] is a relatively big app build using it. It also identified highlights to some extent why wait-and-see is still a good approach for non-spare time apps: it's still on v2 because the upgrade to v3 was rather significant.
It's probably good to let the API and the tooling stabilise some more, especially since the latter includes a full-blown compiler and hence also has to replace Babel, as far as I'm aware (which is not too far) - and TypeScript, for that matter.
FYI I've selected Svelte for an enterprise project and after using it for some time, it seems to have some pretty big issues. I would honestly call the current release a beta version.
In particular, there is a _lot_ of flakiness with reactivity and because reactive things are magical in Svelte, it's very hard to diagnose and correct such issues. Reactive code becomes spaghetti fairly quickly once you start adding logic to prevent it breaking.
Those neat out-of-the-box transitions completely break unmounting/remounting as would be the case with, say, changing "pages" (using a router). If there's any transition still going on, the unmount will fail and yet the replacement component will be mounted, resulting in a frankenpage.
It's also maybe _too_ declarative in the sense that certain things that are easy to do imperatively require you to coerce Svelte to achieve them. You sometimes find yourself deliberately trying to fool Svelte into doing an update.
__
But do I regret choosing it? Not really. All frameworks have flaws. IMHO: Angular is a convoluted spaghetti of nonstandardness, React has its head on backwards with JSX, Vue has too many quirks... I'm partial to riot.js which has just been updated to v4, but I have yet to try the latest version.
115 comments
[ 2.7 ms ] story [ 181 ms ] thread- As should be clear in the article, it's very easy to pick up. In the first couple of weeks I got compiler errors, and kept having to look at how props and binding worked in the tutorial, but now I just make components without having to really think about Svelte.
- TS support is on the way (yaay)
- I'd like to know more about server-side rendering on Lambda - ie, Sapper currently wants to use something persistent like Express, but that really shouldn't be necessary.
If you pass generate: 'ssr' to the compile function https://svelte.dev/docs#svelte_compile you get JS that can be used to generate static HTML in a Lambda or anywhere else
In fact the ideal way to use Sapper is without express/polka.
Backbone and Angular were a completely different way of looking at things with a huge advantage. They got popular and became the go-to tool of the day.
React was a completely different way of looking at things with a huge advantage. It got popular and became the go-to tool of the day.
Svelte is a completely different way of looking at things with a huge advantage.
"Only".
Likewise GCC/LLVM is huge, but helloworld.bin is pretty small.
Our ondemand cloud build servers download the code, restore nuget packages and download node modules. Most of the build time is spent downloading. Compiling generally takes an order of magnitude less time compared to those 2 steps.
This especially effects scenarios where end-to-end testing can only be done in a staging environment due to complexity of the product.
Fwiw though, even a 250MB node_modules would pale in comparison to my Rust version lol.
Why does Rust need a node_modules folder?
IME it's not uncommon to see node_modules with thousands of packages.
Do keep in mind of course that these are dev-time dependencies, they don't go into production. IMO only 30MB of build deps is pretty damn good.
(Edit sounds same: https://github.com/sveltejs/svelte/wiki/FAQ#how-do-i-do-test...)
JS libraries sometimes take a non-presciptive approach of "test however you want!", But roll your own testing for a UI framework really limits adoption and enthusiasm at larger companies.
1: https://github.com/testing-library/svelte-testing-library
Which isn't to dismiss the concern — just to offer an explanation as to why it hasn't been our top priority so far.
Not in all cases, I maintain some component libraries (mostly React, but a Svelte one too) and ensuring a standard component interface is pretty valuable imho. Enzyme as an example lets you test React components, props, state, etc in isolation but is not very prescriptive about what you 'should' test.
(thanks to whoever bothered to do this writeup).
https://github.com/gactjs/gact/blob/master/docs/long-live-th...
EDIT: if anyone has proof this is not true, I'd love to hear their counterargument.
For example, even changing a single value in a big list requires the whole VDOM to be recreated, but should be very efficient in Svelte as it can directly modify the specific DOM node. On the other hand, as pointed out in the article you linked, if changing a value affects a large part of the DOM, but does not actually change that much, then value-comparing frameworks (e.g. Svelte) probably do a lot of unnecessary work compared to VDOM-based approaches (intuitively I would think that this case does not occur that often).
Changing branches in a component is extremely common in code I write (very large business application with lots of rules).
Another important optimization is caching and re-using DOM nodes. With a vdom, you know exactly which properties and attributes differ from the default node. To reuse a node you need only update these properties to their new values or restore their original values. Without that tracking, it would be computationally cheaper to just create a new node.
One important example of this is our use of flyweight scroller patterns in lists. The content of the sub-tree changes, but most of the sub-components stay the same, so a vdom could keep most of the dom nodes around.
Here is the repl of the code you posted.
https://svelte.dev/repl/1a70f2f38af94ed7ac8bd032feea52f9?ver...
A Svelte component is mutable & manages the related DOM elements which are also mutable. In the conditional, the tree is re-rendered.
Would React's diff algorithm be able to recycle the `<p>surgical</p>` DOM Node? How much more performant would detaching & reattaching `<p>surgical</p>` be than recreating `<p>surgical</p>`?
Assuming the `<p>surgical</p>` can be recycled, the use case having the largest effect is a large inner tree being wrapped/unwrapped; where the inner tree would simply be moved instead of recreated.
In Svelte, this can be optimized by using a subcomponent, as seen in the repl example. You can examine the compiled js.
I may be wrong, but I believe hyperapp recycles both the physical DOM node and the attached vdom node together (IIRC, they mark reused vdom nodes as "recycled" instead of directly comparing objects so they don't have to construct as many new vdom objects).
Preact kinda cheats here because they diff against the DOM directly.
DOM nodes can actually be recycled relatively easily. Cache the nodes by type then by class. Most recycled nodes would be a 100% match based on those two alone. If type and class match, then you have a super-high probability of dealing with old nodes for the same object, so few modifications are required. Most nodes without classes tend to have no attributes changed (<div>, <p>, etc) so they will match as well. Store those nodes with their vdom attached and you will have a record of what has been modified so patching is fast.
This optimization exists in some vdom implementations and would make the case in question much faster. There also seems to be an implication that the diffing algorithm will bloat. If you look at React, the diffing algorithm is a very small part of the codebase.
This is hardly just an academic optimization though. It is the key to reducing overhead on long lists. With long lists of complex objects, you cannot rely on patching text values because there will undoubtedly be actual DOM differences. Rather than dooming the entire list to poor performance, you can recycle those nodes and retain most of the performance of a flyweight scroller where nodes are all identical.
https://developers.google.com/web/updates/2016/07/infinite-s...
In that very simplistic example, there are only 4 nodes to each list, so creating and destroying them doesn't matter. I have a scroller in a business app where each item has a few hundred DOM nodes. Create and destroy them constantly and you'll definitely notice on a desktop and performance will crawl on a mobile device.
Instead, you want to save those DOM nodes in a cache and re-use them. In order to do this though, you must know what parts are default and what parts have been modified by their previous user. A vdom does this automatically, but the cost for Svelte to calculate which of the hundreds of properties have changed is too big, so they just throw it away and make another.
An even better optimization would be where each list item has the same node structure and only text or images change. I believe Svelte can handle this case. Unfortunately a lot of lists are slightly irregular in real-world applications. I work with these kinds of lists a lot and a vdom keeps it smoother than all the other libraries we've looked at.
How would Svelte know what things had been changed when looking at a node saved in a cache?
If it has to check every property, the cost to check will exceed the cost to create new. If it saves a list of changes, it's essentially created a vdom anyway.
There’s more discussion here:https://mobile.twitter.com/Shub7241/status/11570049077753241....
Also, Svelte has keys like React which can help out. See this example in the tutorial for that: https://svelte.dev/tutorial/keyed-each-blocks
- as Glench mentioned, it's not destroying and recreating stuff unnecessarily. By default it will create or destroy blocks at the end of the `each`, if the length of the array has changed. If you use a `key` then it will diff the input (as opposed to the output) and move elements around accordingly.
- `$$invalidate` is just an implementation detail, and is subject to change. There a couple of directions in which we plan to do so. One is to use bitmask-based change tracking, which would allow us to generate more compact code resulting in faster change checks (e.g. `changed & 7` instead of `changed.foo || changed.bar || changed.baz` when updating the view). Another is to track which nested properties of an object or array have changed — at the moment, `items[i] = item` invalidates all of `items`, but it would be great if we had a way to invalidate `items[i]` instead.
That said; first it was Backbone which wasn't terrible but kinda clunky in my opinion. But then Angular came along and everybody rushed over to that pasture. But then React came along and everybody rushed over to that pasture. Now Vue is appearing to be greener than the others. Is Svelte where everyone will go next?
My point is this: if all these frameworks were so great, why do we keep running to the latest new one? I actually heard a contractor say the other day, "five years ago everybody wanted Ember developers and now everybody wants React developers. I even have those old Ember clients coming back asking for developers to rewrite the Ember projects in React."
Maybe it really is turtles all the way down...
Big claims need big evidence.
Could you give an example with JSX where templating will not cut?
> JSX components are functions or classes which are trivially composable.
This is framework's feature IMHO not language's.
> I can type functions and classes with typescript unlike string templates.
Situation where types are important in other frameworks is JS part not templates part. Could you give an example where typing is import purely in component's return value?
You will lose type-safety when composing components in template-based frameworks. It is jsx part where types are most important. Instead of getting runtime errors because you passed wrong props you get instant feedback from tsserver and compile error.
* I use React with typescript mainly and I understand what you are referring to.
JSX is decidedly not JavaScript, it is an extension to JavaScript.
> I do not have to learn a new language to iterate over an array.
Since you have to use map() and can't use a simple for-loop, not sure how knowing the language itself helps or not. Either way, loops and conditional are really the basics, you pick it up in a day or two for any template syntax.
> I can interact with it using whatever JS libraries I prefer.
Fair enough, but this prevents many optimizations because the render method can produce virtually anything.
> JSX components are functions or classes which are trivially composable.
This doesn't mean something else isn't as equally composable. Components are composable, doesn't mean they have to be classes or functions.
> I can type functions and classes with typescript unlike string templates.
What does this have to do with JSX ? I guess this is more valid claim for TSX. In any case, since svelte is a compiler, it should be possible to type-check components as well. And it doesn't even depend on typescript, so you can get the same static checks with vanilla javascript.
No, JSX is JavaScript. You can write it in function calls or JSX, it's just syntactic sugar.
> Fair enough, but this prevents many optimizations because the render method can produce virtually anything.
No, using a library doesn't mean the function used from the library isn't pure. Yes it could have side-effects, but the point is you aren't restricted. You can use pure functions or anything else.
> In any case, since svelte is a compiler, it should be possible to type-check components as well.
Yes. But it doesn't, and you get it for free because TSX is just TypeScript. If wishes and buts were candy and nuts...
Svelte's single file components, similarly, are not "dumb string templates". The compiler applies some correctness checking onto them at build time.
Vue adoption does seems to be tapering
(Naively looking at download counts)
While it might look like the frontend is going around in circles, there are major & minor differences between the technologies, and they have each introduced novel (to JS at least) things... Off the top of my head (this timeline might not be right but it's how I went through it at least):
- Backbone got you away from jquery spaghetti, helped you actually manage your data & models. Often paired with Marionette to handle views (if you squint this is the precursor to components) and bring some order in that part of the app.
- Angular bundles backbone's data handling (services), marionette's orderly view separation (views, directives), but they made a fatal mistake in the apply/digest cycle and maybe encouraging a bit too much complexity. Angular is everything bundled together, with consistent usage/documentation/semantics, a familiar programming pattern (MVC), and a large corporate sponsor in Google it caught on like wildfire.
- Knockout sees Angular's MVC, laments it's complexity and focuses on MVVM -- simple binding of a model and a relatively simple reactive-where-necessary controller
- React comes along and suggests an even simpler world where the only first class citizen is components and everything else comes separate (this isn't necessarily new, there is an article out there comparing it to COM subsystems for windows). React is almost always used with react-router and some flux-pattern supporting data management lib -- these are also departures from how angular, backbone and knockout structured in-application communication (backbone was pure event bus, angular had the usual MVC methods, knockout was just callbacks -- if you have a handle to an observable when you change it things reload).
- Vue sees the complexity that React grew to (case in point: shouldComponentUpdate) and devises a much simpler subset along with a new way to handle reactivity -- using the `data` method of a vue component. Vue made a lot of decisions that helped it stay simple and small yet very productive and this is in large part thanks to React existing before hand.
- Svelte comes on the scene and realizes that truly optimal rendering could be achieved by just compiling away the excess and eschewing the virtual dom all together in most cases. No need to track all the structure if you compile the code with the updates necessary. Don't quote me on this but I think a whole host of things influenced this project -- smarter compilers, better type systems, the ideas around zero cost abstractions & doing more work at build time.
- Ember (formerly SproutCore) is actually an anomaly because it tries it's best to be both angular like (so large, and usable by large teams) and keeping up with the tech as it evolves (see: Glimmer, Octane). Ember also has some innovations, like Glimmer's VM-based approach -- turns out you can just ship binary data representing how to draw your components to the browser and skip a bunch of JS parsing, if you bring your own virtual machine that is optimized to draw the components.
As all this moves forward, there are ecosystem pieces like typescript that have gained tons of steam and changed how people are writing JS code these days.
I still personally feel like I can usually get more done with pure Javascript but, as I said in my original post, at least they appear to be headed in a better direction. I did a project in Vue last year and it didn't entirely suck. Unlike the nightmare that was an Angular project I did two years ago.
BTW, you should check out Mithril[0], it's my current favorite, it's very small and self-contained yet very complete. It's got a slow, cautious moving community, and just enough of what you need and virtually nothing you don't -- very easy to use without bundling at all.
Also, the web components spec[1] is on the horizon and once it lands (and most frameworks support some mode where they spit out web components) we're going to get interop for free.
Also pro tip if you're going to start a new project these days and you need to get in the whole bundling swamp, use parcel. It's amazing, almost always zero config or close to it, and just works[2].
[0]: https://mithril.js.org
[1]: https://developer.mozilla.org/en-US/docs/Web/Web_Components
[2]: https://parceljs.org/
Polymer is really interesting because it represents a kind of return to the early web but with all the new-web thinking -- just drop some custom component on your page (so only needing to think in HTML) and you're good to go.
[0]: https://polymer-library.polymer-project.org/3.0/docs/about_3...
If you were you would have heard this cogent argument dozens of times already as it's fairly common knowledge to people who are into frameworks.
Consider trying to understand why frameworks are created before using them. Understanding the motivations behind a framework will help you navigate the api easily and could change your opinion about whatever frustrates you.
And all of those frameworks were great right up until the point that my client or company had a product requirement that the framework designers hadn't though of and then, suddenly, the framework was working against me instead of for me.
Maybe the distinction is that it really matters which framework, and how it's put together, and how much you have to commit to use any of it.
I think the commenter's question was really more about the diaspora of these tools and why they all exist -- svelte is pretty decidedly not a framework (in fact I don't even think you can make it one, AFAIK there isn't like a "svelte data"). IMO the only full blown frontend frameworks are Ember, Angular and react/vue + react/vue-router + flux-y pattern data store.
For reference, the blog post that you're thinking of is "The More Things Change" [0], which compares React + Flux to a Win32 `WndProc` function. Original HN comments for that thread are at [1].
[0] https://www.bitquabit.com/post/the-more-things-change/
[1] https://news.ycombinator.com/item?id=10381015
React came out a little over 6 years ago and Khan Academy started using it soon after. We haven't been itching to switch and, from what I've seen, there are _still_ a lot of people adopting it. Its model is working pretty well, generally.
I like that Svelte is taking a different approach. To move away from React will take something that's as big a switch as the jQuery+Backbone switch was when React came out.
If last years processors were so great...
If steam engines were so great...
If the wheel was so great...
Honestly I don't even know why we bothered inventing fire
One that I recently read involved a solution to the "Challenge Problem" [1] (simulating the movement of a rover) which involves lots of interesting properties and allows one's idea or framework (or whatever) to really battle test the grounds with reality.
On the web however it's different... we're somehow stuck with todo-lists.
1. https://mdetools.github.io/mdetools18/challengeproblem.html
To demo or teach a front-end framework, you need to show:
1. How data gets rendered to the DOM
2. How collections are handled
3. How events are registered and handled
4. How the DOM is updated when data are changed
5. How form inputs are represented
The easiest thing to do is to show an array getting rendered as a list, then add click handlers which change the list somehow, which naturally segues into showing how the DOM is changed. Adding new items or deleting items also answer important questions about how exactly collections of data are mapped to collections of elements and how updates are happened. Finally, no demo of a front-end framework can be considered complete unless it addresses how form input elements work; adding functionality to add a new item or update the text of an existing item is an obvious way to demonstrate this.
A todo-list gives you pretty much 0 insight into almost any of these facets. Let's be honest here, it's a "hello world" cheap demo to quickly showcase: "here's how my new framework works" and you can quickly understand it.
But you have no way of understanding whether those framework decisions actually work at scale. More complex examples are a good thing, not a bad thing :)
This new Bladderbuster framework is amazing because it compiles to negative KB. It has zero features and is really slow but negative KB!
How is it nice that you have almost 30MB of code for something that prints "Hello World"?
EDIT: For what it's worth, I don't fault Svelte for this necessarily. This is indicative of NPM bloat which is becoming rampant in my opinion.
"Another nice thing: the node_modules folder for this Hello World Svelte app totals only 29MB and 242 packages. Compare that to 204MB and 1017 packages for a fresh Create React App project."
I am actually laughing here at this comment. 30 bloody meg.
Never mind ageism in tech, this sort of thing will give me a heart attack before I'm halfway through my career. :D
I can drive a Hummer H3 the block away to the 7-11 but wouldn't it be better if I at least try to ride my bike up there whenever possible?
A compiled Svelte app is tiny. Taking the TodoMVC demo app as an example:
React [1] : 289 KiB over the wire (decompresses to 1,255 KiB)
Svelte [2] : 28 KiB over the wire (decompresses to 41 KiB)
---
[1] http://todomvc.com/examples/react/
[2] https://github.com/sveltejs/svelte-todomvc
- It's using an ancient version of React (0.13.3)
- It's a debug build of "React with addons", not a minified prod build
- It appears to include `JSXTransformer.js` as a separate script to handle in-browser JSX compilation
If you were to redo this using a modern version of React and a standard CRA build, I guarantee it would be _much_ smaller.
edit
Just for kicks, I did a quick search and dug up a pre-existing React "TodoMVC" app based on CRA ( https://github.com/ChrisWiles/React-todoMVC ). It's 3 years old, but it was trivial to bump the requirements up to the latest versions of React and react-scripts.
From there, running `yarn build` says that:
The actual sizes on disk are: So yeah, Svelte is certainly going to result in much smaller bundles than a React app, but you have to use a legitimate fair production comparison.https://github.com/developit/preact-todomvc
https://medium.com/@ajmeyghani/javascript-frameworks-perform...
That said, I don't know that 6K vs 40K is particularly significant. For small apps, it disappears into the noise compared to ads, images, video, trackers, etc. For large apps, the framework starts to make less and less of a total percentage of the total app and often slides into insignificance on that side as well.
It's probably good to let the API and the tooling stabilise some more, especially since the latter includes a full-blown compiler and hence also has to replace Babel, as far as I'm aware (which is not too far) - and TypeScript, for that matter.
[1] https://pinafore.social/
In particular, there is a _lot_ of flakiness with reactivity and because reactive things are magical in Svelte, it's very hard to diagnose and correct such issues. Reactive code becomes spaghetti fairly quickly once you start adding logic to prevent it breaking.
Those neat out-of-the-box transitions completely break unmounting/remounting as would be the case with, say, changing "pages" (using a router). If there's any transition still going on, the unmount will fail and yet the replacement component will be mounted, resulting in a frankenpage.
It's also maybe _too_ declarative in the sense that certain things that are easy to do imperatively require you to coerce Svelte to achieve them. You sometimes find yourself deliberately trying to fool Svelte into doing an update.
__
But do I regret choosing it? Not really. All frameworks have flaws. IMHO: Angular is a convoluted spaghetti of nonstandardness, React has its head on backwards with JSX, Vue has too many quirks... I'm partial to riot.js which has just been updated to v4, but I have yet to try the latest version.
[0]: https://www.youtube.com/watch?v=4_PTdJq-1rA