Add Spina, a modern TypeScript/ES6-supported specialization of Backbone.
Review Request #12788 — Created Jan. 19, 2023 and submitted — Latest diff uploaded
We make heavy use of Backbone.js, but Backbone has little support for
former is available through a community-driven typing package, and the
latter sort of works but requires some tradeoffs in how classes are
Those tradeoffs are due to a conflict in the way that Backbone
initializes classes and the way ES6 classes are initialized. Backbone's
base objects (
View, etc.) will call
initialize(), and other methods on the class being constructed, which
is pretty reasonable. However, ES6 class construction is not reasonable.
Each class in the hierarchy must call the parent class's constructor
first, and until that finishes, the class does not have a prototype
thisdoes not work). That prevents parent classes from
calling or accessing properties on a derived class.
We've addressed much of this, and are introducing the result as a new
library called Spina.
Spina provides some tooling for delayed class initialization, through
the use of an intermediary class wrapper that's meant to sit in front of
a base class like
Backbone.Modeland through decorators that decorate
each chain in a hierarchy. These help control the initialization order,
ensuring classes are set up correctly.
We have Spina versions of most of the Backbone classes:
Unlike Backbone's versions, our base classes are truly base classes, and
cannot be instantiated directly. Subclasses are required.
Every subclass in a hierarchy must be decorated with the
decorator. This sets up front-end wrapper class that triggers the proper
initialization order and then passes an instance of the actual class.
For most classes (those inheriting directly from
example), there's minimal waste. For deeper hierarchies, there will be
small constructor-only classes that end up in the prototype chain.
This also bundles a fork of
@types/backbone along with it. This
customizes types in the following ways:
Avoids some of the hard-coded method-only types found in places like
Backbone.Model.defaults. While that may have been generally
necessary for Backbone, it was ultimately a hack and it's not
something we'll be needing to deal with as we move to Spina.
Adds support for
interfaces to customize options passed to views.
Our version of the types are opt-in, requiring the following in
Spina does not embed Backbone, so consumers will need to ensure that's
loaded before loading Spina.
And finally, there are improvements to views:
renderInto()methods simplify some
common patterns in our codebase.
modelEventsattribute makes it easy to connect model events to the
view on the first render.
return thisrequirement, simplifying code.
onInitialRender()method allows for logic to execute only on
the first render.
The render behavior was discussed and debated separately, but I've
ultimately added it because we do use this pattern a fair amount (and
has been a pet peeve of mine for years), and the state logic is required
anyway in order to support model events.
Successfully built this and ran through a series of tests in Review Board,
involving new base classes and various levels of subclasses.
Verified that initialization orders and resulting prototype states were
Verified that the types for the various attributes formerly typed as methods
can now be methods or values.
This is NOT 100% tested at this point. There's a lot of real-world
testing required still.