Ever since the first frontend web framework was made, to "optimize websites", it unfortunately started a chain reaction of new frameworks being released every now and then, fixing and improving very niche areas of web development.
I personally, have been using react for last 5 years, and recently switched to a new paradigm: Framework-Less. The idea is simple, to not overengineer a web application, to keep it performant, and true to it's roots.
I am starting a series here, where I will discuss design patterns that I personally use to create framework-less web applications.
Framework-less != Strongly coupled code
React was one of the frameworks that pioneered the idea of using components, to describe isolated parts of user interface, that may synchronize with some central data.
One of the biggest misconception about vanillaJS is that people think component architecture does not applies. Well, they are wrong and it does apply.
Let's get started by defining a simple component, say hello world for our first app.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple Hello World</title>
</head>
<body id="app">
</body>
</html>
<script defer>
function HelloWorld() {
const HelloWorldUI = document.createElement("template")
HelloWorldUI.innerHTML = `<p>Hello World!</p>`
return HelloWorldUI.content
}
document.getElementById('app')
.append(HelloWorld())
</script>
Okay, so this was extremely simple, and maybe even anyone can implement this. This might not convince anyone from using react, rather they might just keep using react because it introduces a bit more imperativeness into the code.
Of-course, I have solution for everything! Let's see some more interesting examples
Signals are extremely lightweight and easy in vanillaJS.
Nowadays, the de-facto way of doing reactivity is signals. A ton of frameworks has started to implement signals into their APIs. But who says we cannot use signals? they are nothing more than a value with a dedicated subscriber base.
type Signal<T> = {
value: T,
subs: new Set<() => any>()
}
And that's it! your signal is ready. Let us use this to make a reactive application, say clicking a button will increment a built-in counter!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple Hello World</title>
</head>
<body id="app">
</body>
</html>
<script defer>
const counter = {
value: 0, subs: new Set()
}
function HelloWorld() {
const HelloWorldUI = document.createElement("template")
HelloWorldUI.innerHTML = `<button>${ counter.value }</button>`
const BTN = HelloWorldUI.content.children[0]
BTN.addEventListener('click', () => {
counter.value++;
for ( let subscriber of counter.subs ) subscriber()
})
const onUpdate = () => {
BTN.innerText = counter.value
}
counter.subs.add(onUpdate)
onUpdate()
return HelloWorldUI.content
}
document.getElementById('app')
.append(HelloWorld())
</script>
It seems like I am in full control of the code. When I want to update, and what I want to update, is always under my hand. But you might say, "I use folders to neatly store all the components and files and resources and .."
Well, you can always use vite, or even better, BunJS with pure vanillaJS. It works just like react, and is actually super effective.
What about dynamic arrays? and memos and memory hogs and yada yada?
Well, since you are in complete control of the application in frameworkless, you are responsible for implementing all the features that you may want to use, which I will soon address in upcoming parts.
The best part is, the size of the code that you see, will be exactly, if not less in the production build on the interface contribution, because the abstractions of framework or runtimes will never happen.
Can we make Todo application?
If we can make react with javascript, then make todo with react, ofc we can make todo app with plain js. We can do server rendering, maybe even magnitudes of time faster than react or such frameworks.
I will cover all the topics: from organizing to server rendering, and using libraries (external), and even making UI libraries and uploading them to npm.
Framework-less is a way of writing javascript code that produces optimized and to the point code, without the additional and unnecessary overhead of runtimes and framework.
What about abstraction?
Abstraction is always great! If routing libraries or UI libraries for framework-less does gets released, I will happily use them! you might think that how can I advocate for abstraction when I am using vanillaJS?
The thing is, javascript was always there to be used as a "framework to make web apps". If we can abstract long lines of repetitive code, that outperforms in general, and is not tied to any toolchain, I think it's a win!
What's next?
Today I just discussed my framework-less approach. In next parts, I will go deep into fundamentals like reactivity, array-dom synchronization, cached components, organizing components, server rendering & much much more.
Top comments (0)