MarionetteJS + Brunch Part 2— Application Entry-Point

Renato Pestana
Marionette.js blog
Published in
6 min readOct 17, 2017

This article is part of a series about MarionetteJS and Brunch.io. While I try to keep the articles as abstract as possible so they wont depend too much on previous ones, I would encourage you guys to read all the previous articles as I go about explaining tons of concepts that may help you understand the articles better.

< Previous
Next >

Hey there fellas,

Its been a while, work is very time consuming and I never had the time to continue the series, but I hope I can now maintain a steady upload rate :D

Previous article we talked about the firsts steps needed to start our App, requirements, brunch.io configuration and getting us a boilerplate, so for now on we will focus on MarionetteJS.

As a first entry we will talk about Mn.Application (For the sake of time and keyboard lifespan, I will refer to MarionetteJS as simply Mn). Back in the day, backbone didn't had a clear entry-point for your application so a lot of people where struggling to understand where they would do all those tasks that you clearly want to do before anything else, like starting your Router or fetching some initial data. This could lead to some breaking decisions especially if you depend on loading order for data instantiation.

Thankfully with Mn,that got sort out. Mn provides an explicit entry point for your application, making your life easier to initialize everything you want before the actual application. And is also extremely easy to implement and understand, that’s one thing I love about Mn , both naming and structure decisions where very well made and have been improving since day one, so you can almost automatically know what that specific component of Mn does just by looking at his name, and is very intuitive to use given is simplistic structure.

Here’s an example of Mn.Application usage:

//Imports `Application` from MarionetteJS
import { Application } from 'backbone.marionette'
//Extends Application as your entry-point
const App = new Application.extends({
region: '#app',
onStart(){
...
}
});
//Starts new Application when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
const app = new App();
app.start();
});

As you can see, its extremely easy to do, and just by looking at it I bet you can get a very good grasp on what its going on!

Application Life-Cycle

You may have noticed the onStart() method and presumed its purpose was to initialize what you want when the Application first starts right?

Well, guess what? You are right!

onStart() is a method that belongs to Mn.Application life-cycle and its purpose is to indeed initialize stuff when the app first starts, but its not the only one. Mn.Application has two methods as part of its life-cycle: onStart and onBeforeStart .

At this point you may (or may not, lets just assume you are for the sake of my so perfectly written script :P) thinking something like:

“But hey, whats the purpose of having those two different life-cycles? Can’t I just, like maybe, do everything inside one or another?”

Well, you definitely can and there’s nothing wrong (like breaking you app wrong) about it, but think about this. Our first problem was “where am I going to put all this stuff I need to load before anything else” right? That problem was solved by using Mn.Application and that’s great, but that doesn’t necessarily mean you are 100% safe of application initialize problems.

Why? Well, you still have to make sure you initialize everything in the right order! Imagine your first Mn.View uses a specific Bb.Model (if you guessed thatBbstands for Backbone, you are on the right track), but you only instantiate the Bb.Model after the Mn.View , then your application will most likely still fail. In order to try and address this “problem”, the creators of Mn created two different life-cycle methods to separate this logic, so by convention at onBeforeStart is the place you will want to setup up things like router, models, collection and initial data fetch, and at onStart showing your views and initialize Bb.History . By doing this, you can only mess up your app initialization if you maybe are still confused about your loading order of events or if you didn't actually read the article :|

Application Region and Root Layout

You may have noticed the region key at the above example code and may be wondering what it is, as I can agree its about the only thing in the code that may not be self explanatory.

I will talk about regions more thoroughly in another article, but in sum Mn.Regions are a very great way to manage different portions of your view. Until Mn v3, there was a specific view called LayoutView(as of now, every view is aMn.View) and as you probably guessed it was used specifically to define a layout for your application.

Lets look at example below:

We could define our LayoutView to have all this different sections, and each section would be a Mn.Region , so we would end up with something like:

regions: {
headerRegion : '#header'
navRegion : '#navigation'
mainRegion : '#main'
sidebarRegion: '#sidebar'
footerRegion : '#footer'
}

Regions are defined inside a Mn.View by using the above configuration, a simple object with a key of regions , and then a list of key-value items, where the key is the name you want to give to that region, and the value is a jQuery selector of an actual existing element on the DOM (Not having the element on the DOM will give you a better Horror story than IT) .

This is extremely useful for View Re-rendering. Lets say you rendered all your different views in all your different regions. On good’ld days, if you had like a contact view and an about view, when you wanted to switch between them you had to re-render the entire page, even tho footer, header, sidebar and navigation where still the same in both pages, degrading performance. Yes you could do it via JavaScript but it wasn’t very nice to do.

But if you use Mn.Region this is no longer a problem, you can keep your footer, header, sidebar and navigation regions intact and then only re-render the main region with either the contact or about templates, making your application more performatic, your code cleaner and avoids code duplication.

Mb.Application is your entry-point so its only natural that you want to define a main region and a root layout for it, as a parent for all other regions and layouts. Because of this, Mnv3 came with 2 new ways to do this, region attribute and showView() method.

We talked about how regions where defined inside a Mn.View but Mn.Application is an exception to allow you to create a “parent region” for all your application, same rules applied.

The showView() is a method specifically design to render a RootView or RootLayout (whatever you want to call it) inside the “parent region”. This RootView is just a normal view with defined regions to render all your other view (the image above is a very good example of a RootView) . It should also be the only view to be rendered inside your Mn.Application and all the other views are rendered inside it.

Access attached Regions and Views

Ok, so now we have our application initialized and the day just got shinier, but there’s only one thing left, how do I access a specific region or view inside a region after the app has initialized?

Well, Mn.Application provides us with 2 simple methods to do so:

getRegion(<region_name>) : this method allow us to access a region by passing its name as an argument. Now we can access the entire structure inside it.

getView() : This method allow us to access a view inside a region, so after you use getRegion() to access the region, you can chain getView() to access the view inside it.

And that’s it, you now have a very good grasp on what Mn.Application is and how to use it. I hope you enjoyed the article and that it has been useful to you in some way.

Any questions feel free to ask and I hope to catch you guys on my next article.

Cheers ;)

--

--