02 Sep 2020
I’m once again at the crossroads of a new project and deciding what to build it in.
I know Rails. I could build it in Rails.
It may very well remain a prototype. It may very well amount to nothing. I might as well write it in Rails.
But that’s not optimistic is it? And worse - it’s boring. And not to reject The Boring Stack, but part of why I’m developer is because I like figuring things out. Part of that is in building products, but part of that is in using cool technologies.
Anyway, I want to make sure I’m using the best tool for the job. That’s why I’m learning Svelte. And that’s why I’m thinking I may start this new project in Elixir/Phoenix.
Okay, Pros:
- Elixir scales easier, handles many more concurrent connections, uses fewer resources, blah blah blah. Again, this project may just become nothing. Could be no one uses it. But the “uses fewer resources” part becomes relevant here, because the fewer resources it uses, the longer I can keep it up and wait for it to gain traction without being tempted to scrap the whole thing.
- Anyway, even if nothing comes of the project, I won’t come away with nothing. I’ll still have more experience with Elixir/Phoenix. If I build it in Rails, I probably won’t learn very much.
- Phoenix and Elixir apparently allow a lot of the expressivity of Rails and Ruby. That’s a good thing. Maybe I won’t be able to build things as quickly, but I can end up buildings at 90% the speed I could with Rails for even 500% the performance boost, that’s a worthwhile tradeoff, isn’t it?
- People enjoy coding in Elixir. If I enjoy it, that would be a worthwhile thing to discover.
Cons:
- This thing gets built slower than with Rails, since I don’t really know what I’m doing yet.
- This thing gets built potentially worse than with Rails, since I don’t really know what I’m doing yet.
- If I ever want to find people to help me (like if I make the project open source so community members can contribute), I’m going to have a much harder time finding people who can write/learn Elixir than Ruby. This is a non-negligible potential issue.
- I’ll lose some of the edge I’d have over competitors from development speed.
- My current experience with Elixir involves me taking exorbitant amounts of time reading through docs and code to make sure I write a handful of functions cleanly and concisely in such a way that satisfied both the linter and Parker.
So this could potentially be a painful experience. And it also probably means another few days doing tutorials and whatnot to relearn Elixir and actually learn Phoenix.
But I like learning things, so this could be fun. And not at all a way to put off the hard part of getting this application off the ground, which is getting adoption. -_-
01 Sep 2020
I finally reconstructed the base functionality of the video player web app I’ve been trying to build, formerly in React, now in Svelte.
It’s been a decent experience so far, given that this is my first attempt trying to build something using the Svelte, but I can’t shake the feeling that it just doesn’t feel quite right in the way that React did. This may very well be simply because I’m not used to it, and after all, the main reason I taught myself React in the first place was because it just didn’t make sense to me.
However, while Svelte does make sense to me, it just feels more confusing. I really think it’s that I miss React’s top-down dataflow, among some other things. It was just simpler to conceptualize. Information was always going one way; I could always find the origin of a piece of data in a component, a parent component, or fed to it through a reducer. With Svelte’s bindings and the way it uses stores, it kind of feels like data is just being thrown every which way, which of course is just a matter of perception. But it was easier to conceptualize the flow of data with React, I feel. The dataflow of my Svelte app reminds me of my early Angular apps (and I admit, the fact that I was new to each framework likely has a lot to do with it).
Still, while I really miss the philosophy behind React’s dataflow, I also really resonate with the philosophy behind Svelte’s compiler-based approach and lack of virtual DOM. I could technically recreate the one-way dataflow in Svelte but that doesn’t seem idiomatic so I’m going to keep trying to get used to this way first. Things may be better once I’ve internalized it better (and once I learn how to write good Svelte).
I will say, though, that it hasn’t taken very long for me to run into bugs in Svelte and its tooling. The functionality of my video player app depends on control of the video currentTime, which technically Svelte can bind to. However, I’m getting inconsistent behavior when attempting to update the currentTime while the video is playing (when clicking on a component corresponding to a specific timestamp) and it appears I’m not the only one. The issue was reported as fixed, but it’s still showing to be a problem in my Firefox (while mysteriously working fine in Chrome).
Additionally, when I enable lang="ts", it takes issue with me binding to currentTime, saying it should be currenttime. I’ve just had to disable TypeScript in that component for the moment, which would be much more annoying if I relied more on the language.
Again, I’m willing to bear through these issues in the present for the sake of familiarizing myself with the framework. Once I have a spare moment, I may try my hand at fixing the issues myself.
Anyway, I finished this rudimentary clone of my original React app and after peeking through the Dev Tools of both apps, I made two immediate observations:
-
Both apps were running at nearly 60 fps. I’m not sure I’d ever actually measured the FPS of the React version, but regardless, this isn’t entirely surprising to me. I’d done decent optimizations on the React rendering so it was pretty fast for the use case. “Fast enough.” But fast enough (at least, for now) or not, I could tell that React was maybe not the best tool for the job. Like I said, the app relies a lot on the video time which obviously is constantly changing. A framework that by default tries to re-render entire DOM trees whenever state changes is probably not the best to handle this sort of thing.
The React version runs at 60fps, yes, but it does so with the update function for the currentTime state throttled to every 200ms, and with a lot of shouldComponentUpdates. Svelte gives me the same thing without needing all the boilerplate. The React version just uses component state and currently utilizes the currentTime state in one area, making it easy to optimize. Imagine if I was putting it in a global store; I’d need to define custom shouldComponentUpdates everywhere. With Svelte, none of that is necessary.
That’s why, as soon as I heard of Svelte, I wanted to rebuild this app with it. Not because there were any current problems with performance, but because I knew what was all going on behind the scenes and it pained me. When Rich Harris said, “As engineers, we should be offended at all that inefficiency,” it really spoke into my soul. I don’t want my entire app trying to diff itself every 200ms even if most of it gets blocked by shouldComponentUpdate. And believe me, shouldComponentUpdate has always been my best friend.
Svelte binds to currentTime with requestAnimationFrame under the hood, and everything still runs at 60fps (again, for now). There’s still a ton of room for improving performance down the line if I ever need to. But who knows? Maybe I’ll never even need to.
-
The bundle size was nearly 80kb. 80kb? Well that’s a decent amount below the React version’s ~200kb, but still an order of magnitude higher than what I expected. Well, in retrospect, there was an obvious answer to this dumb question. I first tried creating a new starter Svelte app just to make sure my memory wasn’t failing me and this was in fact abnormal. Built it– bundle size was about 5kb. Okay, so I wasn’t crazy.
I tried adding a video element and some handlers/bindings to it. Maybe there was some extra Svelte machinery (75kb of it…?) that needed to be included when handling media elements and wasn’t considered in most demos that didn’t use video.
Nope. Still negligible bundle size.
I started removing things from the main Svelte app, which was ballsy considering I hadn’t committed anything to git at this point. Nothing changed.
Wait, how big is lodash? About 75kb, it turns out. That could be it.
I removed lodash imports. 5kb. Merde.
But wait, I had barely imported anything, just a handful of things like import { times } from 'lodash', so why was it including the whole bundle? This is 2020– isn’t tree-shaking a thing?
Well it turns out this person on StackOverflow had the same question. This is how I learned that the normal lodash module on npm isn’t actually an esmodule and thus can’t be tree-shooketh. I can’t be the only person who never realized this, especially since at my last company we had also used the full lodash module unless we were also using babel-plugin-lodash and/or lodash-webpack-plugin and I just never noticed.
So PSA: WebPack can’t tree-shake your lodash unless you use it with one or both of the above plugins, or you use the esmodule version of lodash aka lodash-es.
I re-added the bits using lodash into my code, this time drawing from lodash-es, et voilà: 7.5kb. There’s the bundle size everyone knows and loves.
Meanwhile the React version has been awfully quiet with its 200kb.
Of course, my intention isn’t to bash React or promote Svelte. At least, not in all cases, and not for everyone. For example, I personally wouldn’t suggest Svelte to a new frontend developer. I would instead direct them to React, because even though React also does a lot behind the scenes, it was still essentially all JavaScript.
Which brings me to the main thing I miss about React. Bearing in mind that JSX just gets translated into function calls, React was just JavaScript. All that time working with React didn’t just make me good at React– it made me good at JavaScript.
Svelte is not JavaScript– it’s Svelte. It’s its own language and gets compiled to a separate set of instructions that aren’t immediately obvious from the code you write.
It was one thing to use React’s synthetic events: onClick still feels like attaching a real event handler to a real element. But Svelte’s bind: isn’t like anything in HTML or JavaScript. You can get used to exporting your props as variables at the top of a file, but it doesn’t feel like JavaScript. There’s so much in there that boils down to “Because Svelte” and I’m not saying that’s a bad thing, but I miss just being able to rely on my JavaScript knowledge to get me by.
En tout cas, my main goal here is to keep learning about and acquiring tools that fit various use cases for software development. I’m learning Svelte because the paradigm it espouses strikes me as a particularly useful and important one, especially for this application, and maybe especially for modern web development. My high school music theory teacher told our class that learning various theory concepts was essentially just adding to our “bag of tricks”, and I think of these programming tools and paradigms the same way. For now, I just think Svelte is the best tool for this job.
28 Aug 2020
It’s been a while since I’ve tried to start a personal blog, and there’s nothing like a pandemic to spur the effort.
I’m working on some new things and figured I would try to write about it. I’m using Jekyll because, well, lots of people use it, and I already have my hands in a bunc of different efforts without having to learn another cutting edge platform. I would have gone with Hugo if I’d ever gotten around to learning Go (or at least, finishing learning it) and I was looking at Elder.js since I’ve been really interested in Svelte lately, but I really don’t want to be on the bleeding edge of some new static site software when all I want is a simple blog.
So here I am.