Comprehensive foundation for Backbone-based modular web application that works!
Based on Grunt task runner and created with latest versions of NPM dependencies.
Application can consist of scripts written in JavaScript and CoffeeScript as well.
This boilerplate contains Backbone application example with sample test specs to let you easily dive into the workflow.
You must have Node.js and GIT installed.
# Clone repository
git clone https://github.com/antarasi/backbone-boilerplate.git
# Rename directory to your own project name
mv backbone-boilerplate my-project
# Need to go deeper
cd my-project
# Install dependencies
npm install
Optionally:
# Remove existing git data
rm -rf .git
# And create your own repository
git init
git add .
git commit -m "Initial"
There are 3 main tasks to run:
npm start
(equivalent togrunt development
or justgrunt
)
- create browserify bundle
- compile SASS
- copy assets
- minify images
- create local dev server
- run tests
- watch for changes
npm build
(equivalent togrunt production
)
- create browserify bundle (minified)
- compile SASS (minified)
- copy assets
- minify images
- run tests once
npm test
(equivalent togrunt test
)
- run tests once
Backbone files should be placed in app/modules/<modulename>
. Each module should have its Backbone directory structure, for instance:
app
modules
repositories
collections
repos.js
...
models
repo.coffee
...
views
repo.html
repo.js
repos.js
...
You can also place general purpose scripts (custom 404 view for instance) directly in app/modules/
app/collections/
and app/views/
.
Application root file is app/main.js
that depends on app/router.js
and all app/modules/*
files that are bundled together using Browserify require()
into dist/bundle.js
.
main
is the default module that is invoked in app/router.js
index: function () {
$(function() {
var MainView = require('./modules/main/views/main');
var mainView = new MainView();
mainView.render();
});
},
Requests that does not match any pattern in Router are resolved by notFound
function.
Main index.html
file that is initially served to client's browser contains
- Favicon
- Compiled stylesheet
- MainView container (for main module)
- External libraries
- Generated application bundle
Find out why external libraries are not bundled together with application scripts in Global libraries section
Browserify bundler is configured to be able to fetch external html templates instead of inlining them in your Backbone.View scripts.
For example we have a module with the following files in views dir:
views
repo.html
repo.js
...
repo.html
<span><%- name %></span>
repo.js:
'use strict';
var fs = require('fs');
var template = fs.readFileSync(__dirname + '/repo.html', 'utf8');
module.exports = Backbone.View.extend({
...
template: _.template(template),
...
});
jQuery, Underscore and Backbone scripts are globally available so we don't have to
require()
them. Find out more in Global libraries section.
Then in generated dist/bundle.js
the above code fragment will be compiled into
'use strict';
var template = "<span><%- name %></span>";
module.exports = Backbone.View.extend({
...
template: _.template(template),
...
});
All styles (SASS / SCSS / CSS) sould be located in app/styles/
dir to be properly compiled into dist/css/style.css
.
Task runner will create temporary app/styles/compiled/
dir for SASS/SCSS equivalents in plain CSS with source maps.
Images should be located in app/img/
and app/styles/img/
to be properly minified.
app/img/*
images will be relocated to dist/img/
app/styles/img/*
images will be relocated to dist/css/img/
All other assets should be placed in app/assets
dir and will be relocated to dist/
.
Relocation respects original directory structure.
3 reasons why I don't bundle libraries like jQuery or Backbone together with application scripts:
- Making libraries exposed as global variables makes your code simpler and cleaner. You no longer have to put
var Backbone = require('backbone')
in each header of your scripts. - Encapsulating all libraries within one bundle.js significantly increases load time (~50%) at slower connections.
- Including libraries as separate script tags from CDN allows the browser to load them simultaneously.
More details about that approach is described here
Download and save as a dependency
npm install <libraryname> --save
Add your library script from CDN (same version) in /index.html
file before bundle.js
<script src="https://cdn.source.com/libraryname/1.0.0/libraryname-min.js"></script>
<script src="bundle.js"></script>
Make your local library script available for test specs in build/tasks/karma.coffee
files: [
#libraries
'node_modules/jquery/dist/jquery.js'
'node_modules/underscore/underscore.js'
'node_modules/backbone/backbone.js'
'node_modules/libraryname/libraryname.js' <------ here
...
]
into app/vendor/<libraryname>
dir and include in /index.html
before bundle.js
<script src="app/vendor/libraryname/libraryname.min.js"></script>
<script src="bundle.js"></script>
Make your library script available for test specs in build/tasks/karma.coffee
files: [
#libraries
'node_modules/jquery/dist/jquery.js'
'node_modules/underscore/underscore.js'
'node_modules/backbone/backbone.js'
'app/vendor/libraryname/libraryname.js' <------ here
...
]
If your library size is small and used only in few scripts, consider bundling it together with application scripts and
require('libraryname')
explicitly where needed because advantages of globalizing it are barely distinguishable then.
Karma
is used as a test runner, Jasmine
as test framework.
Tests are run on PhantomJS
- a headless WebKit based browser.
You can change browser that runs test to:
- Chrome
- ChromeCanary
- Firefox
- Opera
- Safari (only Mac)
- IE (only Windows)
- Install Chrome launcher
npm install --save-dev karma-chrome-launcher
- Edit
build/tasks/karma.coffee
:
a) change browsers
from PhantomJS
to Chrome
b) change plugins
from karma-phantomjs-launcher
to karma-chrome-launcher
You can write tests in .js
and .coffee
as well.
Test specs (including examples) are located in test/tests
dir.
npm build
and npm test
tasks generate code coverage to test/coverage
dir for each browser separately.
After running npm start
task, Grunt watches your files for changes and refreshes browser contents with livereload when needed.
app/*.js
orapp/*.coffee
changes ==>dist/bundle.js
is created (+livereload)app/*.html
template changes ==>dist/bundle.js
is created (+livereload)app/*.scss
orapp/*.sass
style changes ==> SASS compiles todist/css/style.css
(+livereload)app/style/img/*
image changes ==> png, jpg and gif files are minified intodist/css/img/
(+livereload)app/img/*
image changes ==> png, jpg and gif files are minified intodist/img
(+livereload)app/assets/*
file changes ==> asset files are relocated todist/
(+livereload)test/tests/*.js
ortest/tests/*.coffee
changes ==> test are run
Licensed under the MIT license.
Inspired by @tbranyen and @quartzmo projects
Created by Adrian Matylewicz @antarasi