Skip to content

spember/backbone-vertebrae

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Backbone Vertebrae

This goal of this project is to create a basic skeleton / structure for Single Page Web Applications. It's meant to act as a guide / suggestion for building a Front End Javascript application. Vertebrae is a culmination of working on several applications over the past year. I've found this structure to be very useful, and I hope you will too.

Technologies

I've incorporated the following technologies into the structure which I consider extremely useful for structuring and driving your front end application:

  • Backbone: Thus the title. Brings decently coherent structure to your app
  • Underscore: Required for Backbone; adds some nice convenience methods
  • Zepto: I generally prefer it over jQuery
  • Handlebars: my favorite JS templating engine; has a nice balance between feature set and being light-weight
  • RequireJS: Asynchronous module management for your front end code. Really can't say enough good things about it. Once you understand how it works, you'll be writing highly modular, easily testable code in no time.
  • Sass: Helps to manage your CSS

Additionally, for development/deployment purposes Vertabrae also includes:

  • NodeJS: The only way to run your server-side JS. Required by several build tools (e.g. Grunt)
  • Grunt: Fantastic JS-based Task Runner. Used to drive just about everything: tests, handlebars
  • Karma: Used to be called 'Testacular'. A JS Test runner that can execute your tests in multiple browsers simultaneously, or go headless via PhantomJS and run in the background
  • Jasmine: BDD JS testing
  • Bower: Package Manager; use to download libraries rather than check into source code

The overall goal of encouraging the usage of a task runner like Grunt is to reinforce and encourage practices from the server-side world to your front end code.

Overview and Layout

The project is structured such that all static assets go into the 'assets' folder, and are then broken down into CSS and JS (if we had images, fonts, etc, they'd go here as well). The CSS folder is further broken down into an 'scss' folder, containing the individual sass files.

The JS folder contains the meat of the project. Here, we have the following folders: app (application code), libs (third-party libraries, including a sub-folder for Bower downloaded code), and test (test code). Within app, we break down further into subfolders for 'templates', 'views', 'models', etc. The test app mirrors this structure, but contains "-Spec.js" files.

In addition, index.html gives an example of how to include the libraries to get started.

Getting Started & Development

  1. Ensure you have [NodeJS][node] (including NPM), Grunt, Bower and Sass installed. Refer to their "getting started" guides to install
  2. Navigate to the project folder, obviously
  3. Configure the project to fit your environment / requirements: Update init.js, init.js, and Gruntfile.js to reflect your chosen project structure if different from this
  4. Install the development dependencies by running: npm install (Note: I sometimes have to execute this twice for new enivronments)
  5. Install the production dependencies by running: bower install (Note: update the .bowerrc file to change the bower installation path)

At this point you'll be able to proceed with development. The goal is to keep your code as modular as possible: construct your code in the AMD format and rely on Require to handle module loading. For example, consider the following View:

	// inject the needed modules
	define(["templates", "backbone"], function(templates, Backbone) {
		// because they're loaded asynchronously, we cannot guarantee they'll be 
		// ready until the return object is parsed
		return Backbone.View.extend({
			// it's minor, but by injecting the templates object we do not have 
			// to worry about the namespace structure

			template: templates.index, 
			className: "content",
			render: function() {
				this.$el.append(this.template());
				return this;
			}
		});
	});

This module has no knowledge of the outside components (it doesn't know the 'shape' of other components, like the global namespace), beyond the Backbone View and the name of the template. Furthermore, by setting up this module loading pattern we can create mocks during testing.

Templates and Markup

All templatized markup should be written in Handlebars and saved in assets/js/app/templates/handlebars. A grunt task will process each .hbs file and pre-compile them into one file, hbs_compiled.js

Tests

All tests should be written as an AMD module with Jasmine syntax. Each file name should end with 'Spec' (e.g. FooSpec.js). See the test folder for an example

Grunt Tasks

  • grunt handlebars: precompile all handlebars templates
  • grunt sass: process the .scss files into assets/css/style.css
  • grunt jshint: run jsHint through all specified files
  • grunt requirejs: compile the source JS files into one file, assets/js/compiled-app.js
  • grunt karma: execute the unit tests. By default this uses PhantomJS, and will watch your js files continously. Any change will re-run all tests
  • grunt: the default task will perform grunt jshint and grunt karma

and finally:

  • grunt watch: this will run a continuous process which watches the .scss and .hbs files, then processes them appropriately if anything changes.

I highly recommend having two terminals open during development, one dedicated to grunt watch and the other to ``grunt karma```. This will alert you immediately of any broken tests, and will automatically refresh your css and templates without you worrying about it after every change.

Application Compilation / Production Deployment

The current setup uses Sass and the RequireJS Optimizer to compile the SCSS into CSS and concatinate & minify the source JS files into one main JS file.

While the SASS task is set to run automatically with grunt watch, the JS compilation is not. I recommend using the source files as part of development, but run the complication as part of your dpeloyment build.

Currently, each task only creates one .css and one .js file, but this could be expanded to create several modules, useful in a larger multi-single page app, or if one wants to create multiple 'bundles' of their compiled files for different pages within a larger application (as opposed to loading all JS all the time).

Using compiled-app.js

The grunt requirejs task creates a compiled version at assets/js/compiled-app.js. The test index.html file loads RequireJS, then loads assets/js/init.js, the main configuration / initialization file. In order to use the concatenated & minifed version, one must tell Require to load it instead. This is done by editing index.html and replacing:

<script type="text/javascript" src="/assets/js/libs/bower_components/requirejs/require.js" data-main="/assets/js/init"></script>

with

<script type="text/javascript" src="/assets/js/libs/bower_components/requirejs/require.js" data-main="/assets/js/compiled-app"></script>

Notes

The compiled CSS and JS files are placed directly in the assets/css and assets/js folders, intermingled with the src code. This could perhaps be separated out into dedicated src folders for the SCSS and non-compiled JS code.

About

Sample structure for Single Page Web Application code, based around Backbone and RequireJS

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published