
I’ve spent five years writing a JavaScript framework - jcormont
https://medium.com/@jcormont/ive-spent-5-years-writing-a-javascript-framework-on-my-own-af1201f4075c
======
pier25
A priori I'm not too crazy about the architecture and nomenclature, but I have
to say that having zero dependencies is a goal more projects should have.

The JS ecosystem is pretty fragile because every project depends on hundreds
of other projects.

The other day I had to go back to a 2 year old Vue project. I found that many
of the dependencies had vulnerabilities so I started updating those. Then
nothing worked because the newer versions changed its API or didn't support
such and such feature. In the end I had to reconfigure all the project from
scratch. And this project was just 2 years old...

~~~
CivBase
Devil's advocate here.

If you hadn't used those libraries, you would have had to implement
functionality from those libraries in your own code. Presumably, your code
would be subject to the same vulnerabilities and probably require even more
work to update. After all, API changes are generally easier to handle than
design changes.

</advocacy>

I do agree that tiny, insignificant libraries like "left-pad" are bad. Imo, a
good dependency is one that significantly reduces the design complexity of a
project.

~~~
vbezhenar
The problem is that you need one function and you're pulling an entire
library. Also you have some limited use-case (e.g. you don't have to support
IE 6), but libraries tend to accumulate all the cruft in the world over the
years, so you're pulling and executing lots of unnecessary code. JavaScript is
too dynamic to reliably delete unused code, so even approaches like tree
shaking, etc do not work well. And left-pad style libraries has its own
problems, yeah.

There are universal utility libraries. jQuery for DOM, underscore for general
utilities. It's OK to use them, because everyone knows them. But if you miss
some tiny function, just write it yourself. DRY principle often brings more
harm than good.

~~~
pojzon
I would argue whether DRY enforces 3rd party libraries usage. "Yourself"
touches the code you wrote, noone asks you to use already written solutions.

------
emmanueloga_
A lot of C programmers build this "utils" folder that they carry around every
project, I'm sure they keep refining the content of this folder through the
years with things they find and adapt to their taste, or refinements of their
own implementations of different algorithms and data structures.

Seems like you did something similar with regards to building web applications
(5 years working on this framework). Good for you! And if you can convince
others to use your stuff, all the better!

I'm trying to focus on writing my own tools too for the kinds of projects I
work on, including fronted development (instead of always be trying to catch-
up with the latest frameworks) [1]. Can't completely ignore the trends or
fashions, though, sadly. A hard balance!

1:
[https://www.youtube.com/watch?v=VvOsegaN9Wk](https://www.youtube.com/watch?v=VvOsegaN9Wk)

~~~
ehnto
I do the same thing, but it doesn't play nicely with the modern JS ecosystem.
I have a library of re-usable JS/HTML/CSS components that I can sling around
at will. But I can't use them on React of Vue projects so easily.

One of the selling points of React/Vue was that components were portable. But
I have seen so few people actually re-use anything in the real world and you
didn't need a library to make re-usable components to begin with.

I believe that re-usability isn't a language or framework feature, it has to
be a personal or team choice to prioritize it. It could be as simple as a
utils folder or as organised as a bunch of modularized git repos but
ultimately you have to choose to organise that way.

------
biesnecker
> No revisions to the architecture, ever.

I'd love to have this sort of confidence in my ability to foresee everyone's
future needs, but I don't. I mean, I agree that having to do full rewrites
every time your framework's version bumps, but promising no changes ever seems
more constricting than necessary.

~~~
jcormont
Sure this is a major restriction but there are lots of systems out there with
architectures that never changed. I think accepting major changes from
framework authors is something we learnt over time, from projects with lots of
people who have lots of ideas and the project ends up swinging in all
directions.

~~~
pknopf
Just remember, coming out with a V2 that has no upgrade path, while still
supporting and improving V1 and V2 doesn't count. ;)

------
neogodless
This is a neat project. Personally, I can't wrap my head around 100% code
"views". A million years ago, I wrote some (almost) vanilla JavaScript
projects where I would do a lot of document.createElement('...') and I never
really liked it, but it got the job done, and it only required that I
understood JavaScript and the DOM. I could make helper classes in individual
libraries that fit my needs. But I would not want them in a framework. Or at
least, if I'm honest, I might want them in "MY" framework, but never one that
I would think ideologically could be used broadly by a variety of developers.

I like template engines to some degree, and I love binding like you find in
Angular. But the first few times I read Angular code, I didn't "get" it,
because it seemed like there was some magic somewhere. Some automatic things
that happen without being explicit. (This was particularly prevalent in
AngularJS, in my opinion.) Never a fan of that. So an explicit coded view
would be preferable. But I think it's probably going too far towards trying to
make web views in code. Similarly, I dislike React for that reason. I'm not
religiously opposed to markup... HTML and CSS from being controlled in your
code. But I still struggle with it, and prefer to do what I can to keep them
inside templates, as HTML and CSS, and not some abstraction.

I do love TypeScript, so for my purposes, I'll happily use Angular 8, having
never lived through the original AngularJS 1.x -> Angular 2.0 transition that
made so many developers unhappy. But I appreciate what you've done, as well as
respect the work and time you've put into the documentation web site. Cool
stuff!

~~~
jcormont
Thanks for sharing your views. The way templates are implemented is definitely
a matter of personal preference, I personally don't like mixing two different
languages, always seemed like kind of a hack to me. With this restriction
Typescene is more like Flutter and SwiftUI, these ended up being very similar.
Can't really compare to React and Vue or even Angular, but I can see that some
people do prefer looking at XML and that's fine :)

------
typon
Sticking to a project for five years and releasing it to the world is not an
easy task. I wish you and the project best of luck.

------
root_axis
Cool project, but I dislike the semi-arrogant tone taken by the author.

> _Have you ever opened a years-old project that used the favorite Web
> framework-du-jour, and tried to make sense of it now? Would you be able to
> maintain such a piece of software?_

Yes? Even if the answer were no, why would this framework be any different?
The author seems to suggest that his perspective on "maintainable" is
universal when it's actually just his opinion. Having strong opinions is fine,
we all have opinions, but trying to play up your own framework as if it's
objectively more maintainable is eye-roll worthy, _especially_ in the context
of JS land.

> _Who will remember the (hypothetical) peculiarities of the willUpdate method
> in version 14.2.132 of framework X?_

This is a banal criticism that can be applied to any piece of software that
introduces breaking changes. The idea that the author will never release
breaking changes is absurd, especially on the web.

> _Code shouldn’t have to be completely rewritten to be compatible with the
> next major version of Typescene_

"completely" and "compatible" are pretty vague caveats. Is it a complete
rewrite if I have to rewrite 25% of code? 50%? 60%? I'm sure someone can point
out an example of a framework that required "a complete rewrite" in order to
be "compatible" with the next major version, but this isn't typical.

> _No-nonsense object-oriented (OO), event-driven approach._

OO is nonsense (someone's opinion).

> _you’ll only need external modules to import complex UI components or
> application behaviors that aren’t included in the framework itself._

You'll only need external modules for complex UI and behaviors that aren't
included in a minimalist framework... So, just like every other framework out
there.

> _Most importantly, Typescene hasn’t been invented overnight, it’s not a
> Minimum Viable Product that introduces some clever new paradigm_

What is an example of a framework that was "invented overnight" that
introduces some clever new paradigm?

I'm not trying to come down on the author, and I'm not making a technical
criticism of the project, but the "everyone else's shit stinks but mine smells
like roses" is a turn off, for _me_ personally.

~~~
_delirium
It didn't really bother me, but I might be reading it more strongly in the
context of this being a single-person job. If a project took a strongly hyped
tone while also having a large amount of money backing it, I might be annoyed
(heck, this isn't a hypothetical, it happens all the time from
Facebook/Google/Amazon!), but this is some random individual who is trying to
explain why their project has advantages, when other frameworks are mostly
backed by large corporations. In that context my reaction is more, "hey, good
hustle, we'll see how it pans out". Maybe it's good, maybe it's not, but if
it's not, it hardly threatens me, because there's no money and little manpower
behind it anyway. There are other strategies to take with a more humble tone,
but I'm not really _offended_ by this strategy, and there's a risk that a more
modest strategy would result in nobody giving it a second thought even if it
_did_ have significant pros. Not that my reaction is correct or anything, just
thought I'd add a subjective reply.

~~~
root_axis
Sure thing. I'm not suggesting that there is anything _wrong_ with the
framework, and just because I find the tone of the blog somewhat arrogant
doesn't mean that I'm _offended_ by it; sometimes arrogance has a reasonable
explanation, I just don't see that here.

> _trying to explain why their project has advantages_

IMO you can do that without the tacit suggestion that the competition produces
unmaintanble code, or at least, explain why this framework is objectively more
maintainable and not just one's particular opinion of what is maintainable.

> _if a project took an arrogant tone while also having a large amount of
> money backing it, I might be annoyed_

I'm not really annoyed either way, but in my totally subjective opinion a lone
developer should take a more humble tone, it's not as if backing by a large
corporation correlates with non- maintainability.

------
ggregoire
> the component factory pattern used by Typescene doesn’t sacrifice
> readability: <foo x="y">...</foo> simply turns into Foo.with({ x: "y" },
> ...).

The JSX version is more readable tho. It looks like HTML. Everybody knows
HTML.

~~~
jcormont
Not saying that HTML isn't _also_ readable (although... once the number of
attributes grows larger I always end up with a bit of a mess, but that might
just be me).

The real feat here is getting rid of the hacky way that XML and/or template
strings and JS are mixed together in the compiler, without _sacrificing_
readability per se.

~~~
FlorianRappl
If it would be 2013 the "hacky" way would be acceptable, but JSX is a de-facto
standard that is supported by _all_ tools used in production (incl.
TypeScript, Babel, your favorite colorizer, language server extensions, ...).

Imho the proposed way sacrifices readability a lot (what does "with" do? is it
like the infamous JS with? what is the first, second, third, ... argument?).

~~~
jcormont
Just read it like natural language. Where it says UIButton.with({ label: "OK"
}), that's a Button With a Label of OK. Editors with TypeScript-aware
autocomplete (e.g. VS Code) will suggest most of the identifiers here, and
tell you what the arguments are for so in practice this works better than you
might think.

JSX is a de-facto standard, and it might be convenient in the way that PHP is
convenient, but that doesn't mean it's not inherently a hack :) ...

------
dmitriid
So many frameworks do this, and I can’t understand why [1]:

    
    
        onClick: "checkTodoItem()"
    

Why? What compells people to go ahead and say: yes, we’re writing everything
in JS/TS which has perfectly fine support for actual functions. That’s why
we’re going to arbitrarily use strings that evaluate to function calls in some
parts of our framework.

[1] See views
[https://typescene.dev/docs/introduction/overview](https://typescene.dev/docs/introduction/overview)

~~~
jcormont
The onClick event handler refers to a method on an object that exists when the
component is _rendered_ , not when the template is parsed by the JS
interpreter. So, to refer to the method itself you'd need to do something
crazy like go through .prototype or something.

Anyway, yes Typescene does let you supply an actual function in place of the
string here, but for me that ruins the 'neat' flow of the view and starts
mixing views with logic.

~~~
dmitriid

       onclick: () => function_to_be_defined_at_runtime()
    

This also lets you deal with functions that are defined at runtime. Moreover,
this actually lets you provide types for the expected callbacks.

> but for me that ruins the 'neat' flow of the view and starts mixing views
> with logic.

How is providing a reference to a function "logic"? You still provide a
reference to a method, only you do it in an unspecified stringly-typed DSL.

Be sides, you're using these magical strings in so, so many places:
[https://news.ycombinator.com/item?id=20310666](https://news.ycombinator.com/item?id=20310666)

This is anything _but_ strongly typed. This is _stringly_ typed.

------
hartator
I've read the article and part of the documentation and I still don't have an
idea what's the added value?

Looking at the code doesn't seem specially appealing:

    
    
      export default UICell.with(
      UICenterRow.with(
        UILabel.withText(bindf("${foo}, world!")),
        UIPrimaryButton.with({
          label: "Do something",
          onClick: "doSomething()"
        })
      )
      )

~~~
futureastronaut
I don't think it's in good taste to use a reserved word like "with" in the API
either. And it feels like it's being used in places where a plain function
call would suffice (you call a function "with" params).

------
pcj-github
Where's the app that you built with it? If you have not actually used your own
"framework" to build a meaningful app, I'd argue you've spent 5 years poised
crouching at the starting block waiting to hear the gun go off. Otherwise, you
can't possibly even begin to understand the realities of working with it. This
is why popular frameworks tend to come out of large active shops that have
real problems to solve.

~~~
jcormont
I do mostly non public work, LoB apps in particular.

~~~
clintonc
Life of Brian? Lots of Babies? Library of Barcelona? Linux on BeOS?

~~~
eberkund
Line of Business I presume

------
devin
I can run Clojure libs that are 5+ years old on the latest clojure with no
code changes. I applaud the author for designing a framework that keeps devs
off the absolute waste of time that is the upgrade treadmill.

~~~
schpaencoder
This is such a great kept secret. Most people just scoffs of when they see a
project on github not updated for a couple of years. Not with Clojure.

~~~
JasonFruit
Even less with Common Lisp, in my experience. There's some rot, sure, and some
dependencies that have disappeared — but there's a lot of things that are no
longer under development because they're _finished_.

------
miles_matthias
Lots of respect for working on a project for 5 years and releasing it to the
world. That's really hard.

Question - do you have financial goals with this project, or do you see it as
a community / hobby project? If so, what are your plans to do that?

~~~
jcormont
I've mostly made this for use with my actual (paid) project work, so the idea
was I 'might as well share'. Turned out to be much more work than I
anticipated :) Definitely not a hobby project though, I'm hoping eventually a
big enough community might pick this up.

~~~
wott
> I've mostly made this for use with my actual (paid) project work, so the
> idea was I 'might as well share'.

Have you made sure you got authorisation to release the code, or that you were
in a case where you didn't need such authorisation? Because in a lot of cases
the code is not the developer's property, it belongs to the company who paid
him to develop it.

~~~
jcormont
Yup no worries, I work with my own standard contract and work like this is
excluded. Valid point though, thanks.

------
paulhodge
The article sure hypes it up but the code doesn't really solve many problems
for you. It's about the same level of a framework as Backbone.js but with way
less features.

~~~
jcormont
Examples?

------
quickthrower2
There’s good old KnockoutJS too. I feel like code written in that will still
be working in years to come.

------
royalghost
Is [https://typescene.dev](https://typescene.dev) itself developed using this
framework or not ?

~~~
jcormont
Not the content itself. There's no need, it's generated by GitHub pages and
works fine (and no issues with SEO).

The search popup is implemented using Typescene though.

------
jbuckner
This looks really nice! The class structure reminds me a lot of UIKit in iOS,
which I really like. Having that layer of abstraction to build UI components
for the web looks quite appealing. Nice job!

------
bloaf
[https://imgur.com/aJJ3nvD](https://imgur.com/aJJ3nvD)

~~~
neogodless
An issue has been logged to the documentation web site, and the creator has
been responsive. I'd imagine it'll be fixed in reasonable time.

------
atarian
The first commit was 3 years ago:
[https://github.com/typescene/typescene/commit/9bc0d9844eed7e...](https://github.com/typescene/typescene/commit/9bc0d9844eed7e14cdc97ab7fce44450e62c1d34)

~~~
mcknz
If this started as part of another app, it could have taken 2 years to isolate
the framework as a standalone piece of work.

------
hizanberg
> a mission to build the most elegant framework ever

The only elegant thing I find about this framework is that it has no deps. A
TypeScript-first framework would be a plus but I find the Typed API
particularly inelegant with its usage of static methods to compose the UI
which is particularly non idiomatic for JavaScript.

There doesn't appear to be any live examples you can experiment with which is
a notable shortcoming for a modern JS framework and the only complete stand-
alone example I can find is something called "first project" that was
contributed 19 days ago:

[https://github.com/typescene/first-
project/](https://github.com/typescene/first-project/)

The name doesn't fill me with confidence and the only example I could find has
a webpack dependency which kind of throws out its "no deps" USP. I don't find
anything compelling in that example that would entice me to use it over React,
Vue or even just Vanilla JS - which I'd prefer to implement this particular
example of which I'm not clear what value it adds that would justify adding a
dependency to this JS FX.

This file is the most code I could find:

[https://github.com/typescene/first-
project/blob/master/src/a...](https://github.com/typescene/first-
project/blob/master/src/activities/main/view/index.ts)

It's full of "magic string" APIs where there's no way you could intuitively
guess what the values would be, e.g:

    
    
       - maxWidth: "100vw"
       - gravity: "center"
       - revealTransition: "fade"
       - borderColor: "@separator"
    

The benefit of using TypeScript is that all these values could be typed to
assist during development and type-checked to validate any runtime errors.

Magic strings are even being used for callbacks that looks like it uses its
own unknown DSL in different APIs of which is going to be unknown to anyone
but the author:

    
    
        - onEnterKeyPress: "addTask()"
        - state: bind("object.complete")
        - onClick: "+ToggleTask"
        - tl("{@text/50%}${todo.nRemaining} task#{/s} remaining")
        - hidden: bind("!todo.nCompleted")
    

The docs are particularly lacking in working examples of which the bulk looks
like an API class dump which isn't a useful onboarding experience for anyone
who wants to learn and use the framework.

Honestly if headline didn't say it took "5 years" to implement I would've
guessed its a few months effort max - nothing like the refined, battle-tested,
real-world validated framework this article proclaims it to be.

------
doitLP
This looks interesting. Well done on making something and putting it out
there!

------
ng12
Why provide a layer of indirection between the developer and the DOM? I
already know HTML elements and the DOM API, why should I want to learn a hole
new framework to construct them?

~~~
pknopf
Everything these days abstracts the DOM. Why use _anything_ then?

~~~
ng12
It's not abstraction it's indirection. You're not using <a> or <button> you're
using UIButton and UILink and whatever a UIExpandedLabel or a
UISelectionController does.

------
franciscop
> a mission to build the most elegant framework ever

This is where it lost me. Why is elegance a priority? What problem is elegance
trying to solve here? Elegance is just a feature, that ill-suits many people
who might be better served by others. Also seeing the examples in the homepage
don't seem very "elegant":

    
    
        // A first Activity, similar to the Controller in an MVC approach
        export class MainActivity extends
          PageViewActivity.with(view) {

~~~
darkerside
Examples aside, here's how I think about elegance. Sometimes you run across,
or imagine in your head, or accidentally stumble into writing some Especially
Good Code. The code just seems to work, extends easily, repels bugs, scales
appropriately, etc etc.

I think what's happened in these cases is, typically by luck, you've written
code that matches up very simply and beautifully with an undescribed and
perhaps indescribable pattern that's present in a larger problem domain. Like
poetry, your code expresses the nuances of that problem in a way that prose
simply can't (efficiently). You can't always tell or explain what's so great
about it, but working with it is a pleasure, and it rarely lets you down. To
me, that's the ideal of elegant code.

------
sansnomme
OP is almost definitely an Android developer.

~~~
pknopf
Why do you say that?

~~~
sansnomme
The style, nomenclature, choice of vocabulary are those of someone who has
spent a lot of time with Android Java.

E.g. see this:

[https://developer.android.com/training/basics/firstapp/start...](https://developer.android.com/training/basics/firstapp/starting-
activity#java)

Compare it to OP's framework documentation.

------
Crazyontap
So basically what this does is that instead of writing HTML I can now write
everything in Javascript, i.e <buttton> becomes "new Button" and then I can
write nested JavaScript code like I write nested elements in HTML.. is that
it?

~~~
jcormont
Yes, for the View part. There are also other components that handle logic and
your data model.

Writing 'new Button' for every single UI component would be really cumbersome,
that's why there's also a 'template' syntax which uses static methods
(Button.with(...) which creates a button factory).

------
jamalrashid
0 dependancy project! That is a worthy goal. Think all projects should have a
live counter of how many dependencies they have and highlight the highest risk
ones

------
NohatCoder
What does this framework actually do?

The introduction bashes some malpractices of other frameworks, but it doesn't
tell me why I would use this framework over Vanilla.js.

~~~
jcormont
I guess a good rule of thumb would be if you don't see the benefit of using a
framework for your project, you probably don't need a framework in the first
place :)

~~~
NohatCoder
I'm not shopping frameworks, I just found it peculiar that the marketing is
all about what the framework doesn't do. It seems like you think that the word
framework in itself describe the purpose.

------
z3t4
This seem to fully abstract the DOM and also CSS, so could probably make it
compile to "native" like react native.

~~~
jcormont
Bingo

------
futureastronaut
Where's the TodoMVC?

~~~
jcormont
Not quite, but maybe close enough:
[https://typescene.dev/docs/guides/first](https://typescene.dev/docs/guides/first)

------
hatch_q
Looks very similar to mithril... with triple the size and no users

------
Tade0
_Strongly typed_

I would refrain from using this term since it doesn't have a single agreed
upon definition.

~~~
GordonS
Especially given the other comment here about using strings for handlers in
views, which seems crazy TBH

------
arisAlexis
Imagine if you spent 5 years trying to make the world a better place or fight
cancer.

There is so tremendous time waste in developer world just inventing new langs
or rewritting new frameworks that do the same.

~~~
mahesh_rm
Imagine if he spent 5 years becoming an heroin addict. There is so tremendous
judgmental attitude in your comment. Let me guess, have you been changing the
world and/or fighting cancer in the last 5 years?

~~~
arisAlexis
there is no logic in this comparison. you can stare at a wall too.

