I have followed the basic tutorials (results in one file after you run r.js)
The problem is, my main.js file at the end is 500KB. That's too big. I want to split it into two files.
I want to optimize my main.js file into two files:
Most people will hit the front page and user profile pages, and I want those to load quickly first (while having the other pages load in the background in the 2nd main file)
The problem is, I don't know how to do this. There are examples like this online, but these examples do not use Backbone. They don't cover how to deal with router and app.js
I'm confused...because I only have one app.js, one router.js...how can I split router.js into two files?
I don't know how to split my project up when dealing with Backbone.
Below is the code
HTML PAGE (the entry point for my Single Page Application)
<html>
<head>
<script type="text/javascript" data-main='/media/js/main' src='/media/js/lib/requirejs/require-jquery.js'></script>
</head>
<body>
Hello
</body>
</html>
Main.js
require.config({
paths:{
jquery: 'lib/requirejs/require-jquery',
jquery_ui:'lib/jquery-ui/jquery-ui-1.10.3.custom',
underscore: 'lib/underscore/underscore-min',
backbone:'lib/backbone/backbone-min',
backbone_viewhelper:'lib/backbone/backbone.viewhelper',
text: 'lib/requirejs/text',
birthdaypicker: 'lib/birthdaypicker/bday-picker',
//more paths
},
waitSeconds: 30,
shim:{
'underscore':{
exports: '_'
},
'backbone':{
deps:[ 'underscore', 'jquery'],
exports: 'Backbone'
},
'backbone_viewhelper':{
deps:['underscore','backbone']
}
}
});
require([
'app',
'json2',
'jquery_ui',
'backbone_viewhelper',
'bootstrap_js',
'bootstrap_select',
'birthdaypicker',
'accounting',
'numbersonly',
'main_alert',
'string_tools',
'plupload',
//more things here
], function(App){
App.initialize();
});
App.js
define([
'jquery',
'underscore',
'backbone',
'router'
], function($, _, Backbone, Router){
var initialize = function(){
Router.initialize();
}
return {
initialize: initialize
};
});
Router.js
define([
'jquery',
'underscore',
'backbone',
'modules/index/view',
'modules/home/view',
'modules/listings_search/view',
'modules/profile/view',
//more modules
], function($, _, Backbone, indexView, homeView,searchView, profileView){
var AppRouter = Backbone.Router.extend({
initialize:function(){
_.bindAll(this);
},
routes:{
'':'index',
'home': 'home',
'register': 'register',
'login': 'login',
'listings(/start/:start)(/num/:num)': 'search',
'listings/create': 'listingsCreate',
'listings/:listing_id/edit': 'listingsEdit',
'orders/listings/:listing_id/create': 'ordersCreate',
'orders/buyer(/start/:start)(/num/:num)': 'ordersListBuyer',
'orders/seller(/start/:start)(/num/:num)': 'ordersListSeller',
'orders/:order_id': 'orders',
'orders/:order_id/messages':'messages',
'*actions': 'defaultAction'
//more stuff
},
index:function(){
app_router_view.show(indexView);
},
search:function(start, num){
var options = {
filters:{
start: start,
num: num
}
};
app_router_view.show(searchView, options);
},
static:function(template){
app_router_view.show(staticView, { static_view: { template: template }});
},
profile:function(){
app_router_view.show(profileView);
},
passResetCode:function(code){
app_router_view.show(passCodeView, {'code':code});
},
//more stuff
home:function(){
app_router_view.show(homeView);
},
defaultAction:function(actions){
this.navigate('/', { trigger:true});
}
});
var initialize = function(){
var app_router = new AppRouter;
Backbone.history.start({pushState:true, root: '/'});
$(document).on('click', 'a:not([data-bypass])', function (evt) {
var href = $(this).attr('href');
if(href){
var protocol = this.protocol + '//';
if (href.slice(protocol.length) !== protocol && href != '#') {
evt.preventDefault();
app_router.navigate(href, { trigger: true});
}
}else{
}
});
};
return {
initialize:initialize
}
});
As you can see , my entire app starts with main.js, goes to app.js, and finally goes to router.js.
How can I split this?
Based on the code you have shared, I've created a sample web-app and committed the code in git-hub.
Application is divided into 2 modules:
main : contains modules/index/view and modules/profile/view
other : contains 'modules/order/view and modules/search/view
When you request for modules/index/view or modules/profile/view, main.js is downloaded if not downloaded yet. Similarly when request is placed for modules/order/view or modules/search/view, other.js is downloaded if not downloaded yet. Remember to use require.js v2.1.10 or greater, as it has bundle feature which is required for generating other.js.
You can further modularize it by defining order, search, profile as independent modules in build.js, so that they are downloaded only when needed.
Output of executing build command :
media/js/main.js
----------------
media/js/lib/jquery/jquery-min.js
media/js/lib/underscore/underscore-min.js
media/js/lib/backbone/backbone-min.js
media/js/router.js
media/js/app.js
media/js/main.js
media/js/modules/index/model.js
media/js/modules/index/view.js
media/js/modules/profile/model.js
media/js/modules/profile/view.js
media/js/other.js
----------------
media/js/modules/order/model.js
media/js/modules/order/view.js
media/js/modules/search/model.js
media/js/modules/search/view.js
The execution flow goes like this:
index.html => media/js/main [it has index/view, profile/view, app.js and all the dependencies]. By default Index view is shown, as it is configured for home route.
When Profile links is clicked, no more files are downloaded, as main.js is already downloaded.
When Search / Order links are clicked, other.js is downloaded.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With