I came across this article about about backbone apps with requirejs. There is one thing that seems really odd. Whenever they need a reference of Backbone, Underscore or jquery in my module I have to require them:
define([
'jQuery',
'Underscore',
'Backbone',
'collections/projects',
], function($, _, Backbone, ProjectsCollection, projectsListTemplate){
var projectListView = Backbone.View.extend({
el: $("#container"),
...
So is there really a need to go that way? Isn't a bit over engineered? Couldn't I just load Backbone and its dependencies before I start my app and use them as global objects like I would do it without requirejs? Or miss I something here?
There are pros/cons either way.
Advantage:
Your dependency management is completely controlled by require.js, instead of relying on synchronously-loaded globally-scoped libraries. It's elegant, modular, and is probably The Right Way to do things.
Advantage:
It's easier to swap in versions of libraries, particularly per-module. I've honestly never seen this in practice - it seems like a "what if" situation rather than something practical. If you do then you're probably hacking something together anyway, sacrificing the "code elegance" you're getting by using them as modules in the first place.
Disadvantage:
You get a lot of boilerplate imports.
define(['jQuery', 'underscore', 'backbone', 'raphael', ...],
In a large app, it could take a half dozen library dependencies before you get to your dependencies. In every module.
The redundancy feels especially unnecessary for Backbone-heavy apps, where each module is probably defining a Backbone model/controller/view - almost every module requires Backbone.
You could wrap them all into a single Lib module that you'd reference like Lib.$(...) or Lib._(...), but that's just moving the boilerplate out of the imports and into the code. It also negates advantage #2.
So which one?
I'd say to look at each library individually and decide whether or not it should be global or its own imported module.
If you're going to use the library almost everywhere (e.g. jQuery, Backbone), then just keep it global.
For other libraries you might only use them in a couple views (e.g. Raphael.js). In that case, import it as a module.
Related
So I have encountered a practice where people will create a module for each component that has service dependencies. that way, when someone wants to use a given component, they dont have to read through the code to see what providers to add to the given module. is this an antipattern? will it cause performance issues or something?
Is there some recommended guidelines on lower/upper limits on how many components/directives/providers/etc should be in a given module? has there been testing of the angular/angularJs ecosystems with 100s of modules on a view? in comparison with if just regular components were all bundled in maybe like 20ish modules instead?
Generally, there are different module types in Angular and guidance as to what they should contain and what modules should import them:
Widget modules - Contains mostly UI components, but no services. Imported by Feature modules.
Features modules - Contains domain-specific private components. Imported by AppModule.
Service modules - Contains services exclusively. Imported by AppModule.
Routed modules - A specialized Feature module, that is the target of routing.
Routing modules - Contains navigation routes and resolver/guard services.
Modules can have dependencies on other modules. For example, a Widgets module could be expected to be used with a Services module, where AppModule imports the ServicesModule, and FeatureModule imports the WidgetsModule. The BrowserModule/CommonModule is an example of this pattern; so is RouterModule.forRoot()/RouterModule.forChild().
I would say its overkill to have one module per component. It would be hard to organize and group common functionality together and leverage services in any meaningful way. It could easily become unwieldy when your imports for a single module run into double-digits.
[Edit]
After re-reading this question, I would like to add a clarification because I think the one-component approach with NgModule encapsulation deserves more attention. I don’t believe in 1:1 module-to-component - that would be overkill. However, I am in full support of 1:many module-to-component where the module exports only one component, and all the other components are private to the module. This latter approach is known as NgModule encapsulation, and it is an excellent way to build your application in a way that loosely couples your top-level components.
If you have a relatively small app then bloating a single module is ok. Once your app starts to get relatively large then it makes sense to start lazy loading modules so your users don't have to download the entire build on app start. Grouping related functionality into modules makes things easier to maintain as well.
So for a smallish site, a single module will be fine but as your app grows it makes sense to start refactoring components and services into modules.
Practically, angular always prefer you to have basic module -
Features module, Shared module, Routing module, Core module,
But if application is big it is better to have lazy loading for modules, to have module for every component is best option, which increase app speed along with this browser load that component which is required.
I have an application made with angularJS, whole application is composed of IIFEs(Immediately Invoked Function Expression). Every module, directive, controller is itself an IIFE and they are around 100s.
I want to know what is the performance pitfall when an app has so many IIFEs.
It is OK to use IIFEs with AngularJS?
How good is using libs like browserify and requirejs with AngularJS for managing the dependencies?
Can you please throw some light on this?
The question you need to ask first is whether you've got some internal parts within the IIFE that you don't want to expose to the global scope.
The whole point of creating a closure in this manner is to mimic encapsulation and avoid polluting the global scope.
The performance pitfall is not so easy to measure; I think the performance issue is negligible when you create the IIFE (don't forget you're just creating a function). One performance issue that I might think of is that when you reference a function variable form an inner function, you need to travel through the scope chain and get it from the closure object.
I would recommend you to look at patterns like module pattern, revealing module pattern etc. I personally use the revealing module pattern.
Browserify and requireJS are two libraries that implement two different specs; the commonJS and AMD respectively. These two specifications try to accommodate a functionality that is not supported by ES3 or ES5; That is a way of defining module and then loading them in specified locations.
If you want to define modules and load them synchronously in a similar manner to hose nodeJS works, you can use Browserify. In addition, Browserify allows you to use the same modules both for client-side and server-side (as long as you're using nodeJS).
On the other hand if you want to asynchronously load your modules you can go with AMD and requireJS, but you won't be able to reuse them on the back-end.
Finally, bare in mind that everything you've mentioned is not directly connected to angularJS; those are some good JavaScript practises to overcome some issues of the language itself. It can be well used whether you're working with angular or not.
I would recommend that you use either browserify or requireJS; it will benefit you in the long run. Just imagine having 100 JS files; you would need to out the manually into your html in the correct order based on the dependency graph. You can easily come across issues like race conditions where one file should have been inserted before another one.
As for the performance overhead of IIFEs, you shouldn't have any serious issues.
As another answer said, IIFEs are a good general practice, independent of AngularJS.
If you're concerned about the performance of IIFEs, go ahead and check out these performance tests on JSPerf (or write your own):
http://jsperf.com/iife-antecedents-in-js
http://jsperf.com/immediate-anonymous-function-invocation
While some ways of IIFE creation are clearly much slower than others, I wouldn't worry about the performance of IIFEs unless you're in a large loop.
I've noticed some people define a new module for each controller, service, directive etc.
angular.module('controllers.Dashboard',[]).controller(...);
angular.module('controllers.Details',[]).controller(...);
angular.module('controllers.List',[]).controller(...);
However, isn't that a performance issue? I mean: for each controller you create, you also create a new module.
What do you think?
Any performance hit would be incredibly minimal. What you do gain in terms of performance though, is testing speed. Testing can be localized to small modules that don't need to load in the entire application to perform what they need to.
On the code organization side, I personally like the idea of breaking up modules depending on feature not architectural slice. So instead of having a module for controllers, a module for services, etc, create a new module for every new feature/piece of the application. This way you can group together conceptually related controllers, views, services, filters, and so on.
The overhead will be minimal in practice. It is really more of a code organization type issue. On my project we have a FooService, FooController,FooDirectives, BarService...
I've been struggling trying to strike the right balance between reusability and complexity when it comes to organizing my Backbone objects into AMD's (for medium- to large-scale applications)
(A) Should every Backbone object (models, views, etc) be in their own module?
(B) Should related Backbone objects be in the same AMD module? (ie: PersonModel, PersonCollection, PersonView objects in the same module definition)
Option (A) seems to allow the most flexibility and reusability, but also the most complexity because of the (potentially) high number of files. While option (B) may make it easier to manage things, but less flexible and really difficult to unit test.
How is (or has) everyone else structured these things?
I good thing about requirejs is that it allow you to abstract the physical files into structured namespaces. You can take the approach (A) and create each backbone class in their own file, then create a "namespace" module to glue all the related classes together.
// Suppose you have PersonView.js, PersonCollectionjs, PersonModel.js as modules
// create a Person module to function as namespace
define(["PersonModel", "PersonCollection", "PersonView"], function(model, collection, view) {
return {
Model: model,
Collection: collection,
View: view
};
});
This keep the modules organized in their own files and gives you some flexibility to write one module per class without requiring you to expose this organization for the rest of the application (I really don't like to have to write require("PersonView", "PersonModel" ... ) every time I need to use the person's objects, it's easier and cleaner for consumers to declare a dependency on a "namespace" instead of independent classes).
For medium to large backbone projects I prefer to use requirejs with a separate module for every model, collection, and view. I also use the "Text" plugin for requirejs so I can load underscore templates just as I would any other module. This for me seems to be the sanest way to manage a large project and I have never really felt overwhelmed with the number of files I have.
+1 on using the requirejs optimizer when pushing your app to production. Works really well.
http://requirejs.org/docs/optimization.html
I just released an open source toolkit which will hopefully help others as much as it helps me. It is a composition of many open source tools which gives you a working requirejs backbone app out of the box.
It provides single commands to run: dev web server, jasmine single browser test runner, jasmine js-test-driver multi browser test runner, and concatenization/minification for JavaScript and CSS. It also outputs an unminified version of your app for production debugging, precompiles your handlebar templates, and supports internationalization.
No setup is required. It just works.
http://github.com/davidjnelson...
I'm working on a fairly large web app in which I am going to be using require.js so I can compile it once it's ready for production, but I would like to use backbone-relational. I am also going to be using backbone-marionette, but I am not sure how it would be included in the define function of modules.
Does anyone have any experience with this?
I'm using Backbone Marionette with Relational and loading them with Require.js. The basic idea is that you need to ensure Relational is loaded. One way to do it is to include Relational as a requirement whenever you define a Relational model.
In my project, I created a simple script called bbloader.js (Backbone Loader) that loads all the relevant backbone models:
define([
'backbone',
'iosync',
'iobind',
'relational',
'marionette',
'marionette.async'
], function(Backbone) {
return Backbone;
});
And then throughout the project, I require bbloader instead of Backbone. For example:
define([
'jquery',
'underscore',
'bbloader',
// ...
], function($, _, Backbone) {
// ...
});
Backbone Relational is already AMD compatible, so you shouldn't need to do anything extra there.
Marionette 100% supports AMD. There's a few wiki pages on getting it up and running, and it's pretty simple:
https://github.com/derickbailey/backbone.marionette/wiki/Using-marionette-with-requirejs
I would assume BB-R works as well, but I don't use this plugin so I'm not 100% certain.