This article is actually quite unlike me - I'm usually someone who advocates against using tools or dependencies when you don't really need them. Stay away from micro-libraries, just copy-past something you find online instead. You probably don't need Lodash in your project - I even made a webpage full of built-in ways to replace every individual Lodash functions with native JavaScript counterparts. But when it comes to frameworks, well, the irony of it all is that even though my little webpage is just static content, I still used a larger framework, and I don't regret it.
There's been a growing outcry against using frameworks on small problems, especially static webpages, and I'm grateful that this pushback exists to help us remember there's other options out there, but if I'm being honest, in many scenarios, the other options just aren't that great. Let's discuss some of them.
No Framework
There are two main things that frameworks give you:
- A templating system, to let you easily build a tree of HTML, sanitizing your data before inserting it to help prevent XSS attacks.
- A reactive system that allows the DOM to be automatically updated based on changing data.
Without a framework, what would normally be a trivial item can quickly escalate into a complicated, error-prone task. Want to see what I mean? Try making a function without a framework where, every time you call it with a list of user objects, it will render or rerender a table of users. The user objects can be as simple as { "id": 123, "name": "Cookie monster" }
. Did you do it? Did you do it right - if you have content selected when this update function gets called, will it stay selected? If you were to add checkboxes to each row, would the checkboxes stay checked after a rerender? Without a framework, a task like this takes quite a bit of intense code. With a framework? Well, in React's case:
const UserList = ({ users }) => users.map(user => (
<p key={user.id}>{user.name}</p>
));
Some other frameworks may have a bit more boilerplate required to define a component, but they all let you perform this actual task in a relatively terse and easy-to-read fashion.
The opposing voice might argue that bringing this sort of thing up is unfair - framework-less development should only be done on static content, to which I would respond that it's more nuanced than that.
My Lodash replacement's page only has static content, but it could grow to be more interactive over time. For example, at the moment I display all examples in JavaScript, but one day I could choose to add a toggle option to let you view the examples in TypeScript instead, or perhaps a button to display unit tests for the code samples, and so on. An otherwise static webpage can grow and receive interactive behaviors over time. If the website's content was written as a bunch of traditional HTML pages without components, then each time I needed to add these kinds of dynamic behaviors, I would need to do refactor quite a bit to componentize pieces of the webpage so it can support those new behaviors. Even some of the existing behaviors wouldn't be possible if I didn't organize the code by components - when you click on a Lodash function, it'll quickly fade content in using a pop-over side-panel. It doesn't require a full page reload. Perhaps in many scenarios this kind of SPA-like behavior is overkill, but for this webpage, I explicitly wanted users to feel as little friction as possible when navigating between different the different Lodash function alternatives.
Web Components
Just use Web Components! They're like frameworks, except native!
No, they're not.
Remember from earlier the two things I mentioned that frameworks give you?
- A templating system, to let you easily build a tree of HTML, sanitizing your data before inserting it to help prevent XSS attacks.
- A reactive system that allows the DOM to be automatically updated based on changing data.
Yeah, Web Components don't do either of those things. The vision is that one day they would, and I can't wait for a future where JavaScript has the most important parts of frameworks built-in, but that day isn't today.
Today, what web components give you is:
- encapsulation, which is admetidly pretty nice, although they're still working out a couple of kinks related to accessability.
- A standard way to define a components so different frameworks can talk to each other, which kind of works, but it is also such a pain to define components this way, use these components, and interop with them. In many cases, it would actually be easier to just make your own ad-hoc component design than using web components. The issues are, in part, because they're trying to mimic the behavior of native HTML elements, and native HTML element lifecycle-management and data-passing is actually quite complex. Now that we get to define native-like elements, we get to inherit all of that complexity, and since frameworks get to interop with them, they too inherit the same complexity. Loads of fun.
Anyways, lots has already been written on this subject, so I won't dwell on it further.
Server side rendering
...is limiting.
Some of the afore-mentioned tasks that are difficult to do without a framework are completely impossible with traditional server-side rendering. Again, consider how I would dynamically populate a pop-up side-panel with content - how would you do that with server-side rendering? An iframe perhaps? That would be quite the hack for an everyday task.
And again, things like being able to toggle between JavaScript and TypeScript examples would, what, require a full page reload and a dedicated URL?
Then there's the fact that this is a GitHub page. GitHub pages, like many other platforms, only lets you host static files. It's much more difficult to find a place that's willing to run your server-side code for you unless you're willing to pay a monthly fee, and I'm not about to do that for a project this small.
What's wrong with frameworks anyways?
As mentioned before, I do like to reduce dependencies when reasonably possible. Each dependency you add is:
- Bloat, as you might be depending on a lot more than what you really need. Tree-shaking doesn't always fix this issue - it isn't magic.
- Another security hazard - dependencies are often changing owners than going rogue.
- A maintenance burden - if you need to use some of the latest features from a dependency, you'd also need to update, which means dealing with breaking changes.
If the benefit of adding the dependency is relatively little, than perhaps it's not worth it. For example, I personally don't see any real reason to install Lodash when the most-used functions are now native functions and the remainder aren't too difficult to just copy from the internet and use. I recognize that there's a maintenance cost associated with copying code and everything, but ultimately, I still favor writing code without Lodash. The amount of time Lodash saves you, all things considered, is typically in the order of minutes or seconds, at least that's been my own experience thus far. On the other hand, opting to go without a framework can cost you many hours of work if future feature requests come in that your framework-less codebase can't support very well.
I also want to add that frameworks aren't inherently as bloated and slow as people make them out to be. Most bloat that you feel when using a React/Angular/Vue/some-other-SPA-framework comes from the webpage being developed with no thought for performance in mind, not from the framework itself. Tell those developers to build something without a framework, and they will still build something that will feel similarly sluggish. On the other hand, take performance-minded individuals and ask them to use a SPA framework to build a webpage, and it's going to be blazingly fast.
Concluding remarks
I'm not trying to preach the opposite extreme here. There are still many, many scenarios where you really should go without a framework and choose one of the other options available. Use your own judgement and some common sense. My main point here is to simply say that, just because your website is small or mostly static, does not automatically mean going frameworkless is best, despite what the current popular opinion may be saying.
Top comments (1)
BTW - I used my Lodash page as an example throughout the article not for any self-promotion reasons. I don't care if anyone clicks on that link. It's because one of the feedback items I got a while back was that I shouldn't have used JavaScript on that webpage as it only has static content. And this is the same kind of perspective I see getting circled around often. Figured it would be healthy to push back on it a bit.