liorch
liorch

Reputation: 23

Backbone architecture with packages

I'm trying to choose a backbone architecture that will best serve my application.

I am building a large application that will be composed of several components or "packages" that can be enabled or disabled.

For simplicity, lets say my single-page-application is a gallery which has several components such as a photo gallery and a video gallery.

I've looked into various solutions - such as requireJs with its r optimizer, marionette and Lumbar but each has some drawbacks: * RequireJS with optimizer or Marionette - I can't see how I can group files into packages * Lumbar - seems it does solve most of my problem, but I could barely find any documentation or community support for it (barely mentioned here on StackOverflow) so I don't know if I can rely on it for a large software project.

Upvotes: 1

Views: 199

Answers (2)

liorch
liorch

Reputation: 23

I've decided that Lumbar is the way to go. Seems like it solves all my of my needs for loading only "enabled" packages, by using it's route-based module loading, as described here: http://addyosmani.github.io/backbone-fundamentals/#route-based-module-loading By declaring each module in the lumbar.json config file, it will create a separate, combined js file for each defined module - and will load the module only if its route was matched. You can see how to do it in thorax-seed: https://github.com/walmartlabs/thorax-seed/blob/master/README.md

Upvotes: 0

Hack-R
Hack-R

Reputation: 23231

Well, this is certainly subjective and you have many choices, but perhaps some background info on some of your choices can help and I'll go out on a limb and recommend Chaplin.

Marionette is nice for many reasons, including that it's developed as an open source project on Github. It's meant to be extremely lightweight and it sounds like your trouble is stemming from its intentionally limited feature set.

Chaplin is a framework on top of Backbone.js library, like Marionette and several of your other options. Both seek to ease the development of single-page JavaScript applications. In such applications, the client performs tasks that were typically performed on the server, like rendering raw data into HTML.

Backbone itself is designed as a minimalist library instead of a full-featured framework. Backbone can only provide the foundation of a JavaScript application architecture. Both Marionette and Chaplin arose because Backbone provides too little structure for real-world apps. They respond to the same problems. So there are a lot of similarities between the two – perhaps more than differences.

Compared to Marionette, Chaplin acts more like a framework. It’s more opinionated and has stronger conventions in several areas. It took ideas from server-side MVC frameworks like Ruby on Rails which follow the convention over configuration principle. The goal of Chaplin is to provide well-proven guidelines and a convenient developing environment. CoffeeScript and OOP

Chaplin is written in CoffeeScript, a meta-language that compiles to JavaScript. However, Chaplin applications do not have to be written in CoffeeScript. In the end, Chaplin is just another JavaScript library.

Using CoffeeScript is part of Chaplin’s idea to make application development easier and more robust. CoffeeScript enforces guidelines from Douglas Crockford’s book “JavaScript – The Good Parts”. Like Marionette, Chaplin is advocating the ECMAScript 5 Strict Mode.

With CoffeeScript, class declarations and class-based inheritance are more compact compared to Backbone’s extend feature. While Marionette tries to get around super calls, Chaplin embraces method overriding and tries to make class-based inheritance work smoothly. For example, if you declare event handlers on a derived class and on its super class, both will be applied. Modularization using CommonJS or AMD

Chaplin requires you to structure your JavaScript code in CommonJS or AMD modules. Every module needs to declare its dependencies and might export a value, for example a constructor function or a single object. In Chaplin, one file typically contains one class and defines one module.

By splitting up your code into reusable modules and declaring dependencies in a machine-readable way, code can be loaded and packaged automatically.

Using AMD isn’t easy, you need to get familiar with loaders like Require.js and optimizers like r.js. As an alternative, you can use the CommonJS module format and Brunch as a processor.

Chaplin provides a core application structure that is quite fixed. It handles the main flow in your app.

The Application is the root class that starts the following parts
The Router replaces Backbone.Router
The Dispatcher starts and stops controllers when a route matches
The Layout is the top-level view that observes clicks on links

In Chaplin, there is a central place where to define all routes. A route points to a controller action. For example, the URL pattern /cars/:id points to cars#show, that is the show method of the CarsController.

A controller is the place where you create models. It’s also responsible for creating the view for the main content area. So a controller usually represents one screen of your app interface.

The main idea of Chaplin are disposable controllers. The basic rule is: The current controller and all its children (models, collections, views) are disposed when another route matches. Even if the route points to another action of the same controller, the controller instance is disposed and a new one is created.

Throwing objects away when another route matches is a simple and effective rule for cleaning up references. Of course, some objects need to remain in memory in order to reuse them later. The Chaplin.Composer allows you to share models and views in a controlled way. You need to mark them as reusable explicitly. If the saved object is not reused in the next controller action, it is automatically disposed.

In a Chaplin app, every object should be disposable. All Chaplin classes have a dispose method that will render the object unusable and cut all ties.

A well-known rule of JavaScript programming is to avoid global variables. Chaplin tries to enforce this best practice. Classes are CommonJS/AMD modules that are hidden in a closure scope. All instances should be private. Two instances should not have references to each other unless they are closely related, like a view and its model.

Objects may communicate in a decoupled way using the Publish/Subscribe pattern. For this purpose the Chaplin.Mediator exists. The mediator can also be used to share selected instances globally, like the user object. After creating the necessary properties, the mediator object is sealed so it doesn’t become the kitchen sink of your app.

Chaplin is also strong at view management. It has app-wide named regions and subview managing. Chaplin takes a different approach on rendering views and attaching them to the DOM. Views may have an autoRender flag and a container option. With these enabled, views are rendered on creation and are automatically attached to the DOM. Instead of container, you can specify region in order to attach the view to a previously registered region.

In Chaplin other than the app-wide regions there are no abstraction classes like Marionette.Layout and Marionette.Region. In a Marionette app, you typically create several nested Layouts and Regions. In a Chaplin app, you have fewer key regions and directly nest views inside of them. Of course you can create reusable views that behave like a Marionette.Layout, for example a ThreePaneView.

Upvotes: 1

Related Questions