25 ms·
Lessons Learned: A Year with a Large AngularJS Project
- maaaats 13y agoI liked the part about structuring the code/files. As you, I'm not a fan of the seed-app where you have one js file for controllers, one for directives etc. Makes it hard to find the stuff I'm looking for, and there will be merge conflicts.
- brandonsowers 13y agoWe learned the same lessons with the chat function Babblr. Structuring the code/files is highly affective.
- danso 13y agoHaving just built a hobby Angular.js app, it's cool to see that it fits large aims. For personal use, I found it incredibly refreshing to use, even as bizarrely different as it was to anything else I've tried. Not in a bad way, but in the sense that it was more convention than I was used to (outside of Rails) I would add that the Yeoman build manager is an absolute delight to structuring and managing your project. It was so slick that when making my first Angular app, I also ended up learning CoffeeScript to kill two birds at once...Yeoman made this otherwise prickly situation as smooth as possible. And I also would agree that directives are Angular's killer feature...and unfortunately for me at the time, one of the hardest to grok because of their magic. Anyone writing an Angular tutorial would do a great service to emphasize the power and use cases for directives.
- bsaul 13y agoyou absolutely should look at the videos on egghead.io about directives. they are a must read as they go very deep into the subject while keeping things extremely easy to understand.
- joelhooks 13y agoOn this project we are saddled with Maven, you are right. I am gonna add a section on build.
- thisone 13y agore directives two places really helped me go from wtf to, "hey I can do that!" (and now I'm onto transclusions) http://www.egghead.io http://www.egghead.io as mentioned and the Angular meetup video about directives: http://www.youtube.com/watch?v=WqmeI5fZcho http://www.youtube.com/watch?v=WqmeI5fZcho The documentation for Angular is dense. As in I've found myself having a lot of "ahah!" moments from reading 3 words. I'm actually starting to annotate it on my blog as I find stuff out. All that being said, I'm using Angular to make single page app prototype very quickly, coming from having no experience creating single page apps, but with a fair few years of MVC under my belt.
- joelhooks 13y agoThe angular internals is another great resource for directives, as the framework itself uses them heavily.
- ezequiel-garzon 13y agoIf you don't mind, what is your blog? Thanks.
- ccera 13y agoI found this helpful in understanding how to use directives: http://thesmithfam.org/blog/2012/12/17/communicating-between-directives-in-angularjs/ http://thesmithfam.org/blog/2012/12/17/communicating-between...
- zenocon 13y agoI agree on this. Angular is awesome for organizing large JS, and making re-useable components. Directives are a killer feature, along with DI (to facilitate testing) and 2-way binding (to eliminate all the boilerplate glue you'd have to write with something like Backbone). The team I'm on recently set up a fantastic Grunt build that incorporates Jade, Stylus, Angular, Google Closure Compiler along with testing infrastructure that works with CI/Jenkins using Mocha, Phantom, Sinon, Chai. It makes developing web apps fun again. Right now, we don't pull in any other libraries aside from Angular. We've found we don't need jQuery anymore, and are able to build up re-useable widgets with directives and use them across projects.
- Kiro 13y agoRe-usable widgets with directives sounds great but the problem I have (with widgets in general?) is that every situation requires a slightly different widget which means the directive gets polluted with conditionals and stuff. For me it sounds good in theory but never works in practice.
- onehp 13y agoEverytime I read an Angular postmortem I'm intrigued that I never see memory issues being raised. In a recent rewrite of one of our applications into Angular we had huge issues with it consuming memory. I think our use case is quite distinct, we have a telephony component that needs to stay loaded so single page app really does mean single page app for us, but even so I would expect to see memory mentioned every now and then.
- zenocon 13y agoI haven't had significant memory issues with Angular. Have you profiled your app? Where is the large portion of memory being consumed. The apps I'm building are being deployed on an embedded system with a custom WebKit -- where the memory constraints are significant (the hardware has a total of about 400MB RAM for everything) -- so I'm pretty conscious about memory issues, and we did test/profile Angular on this hardware and did not find issues. That isn't to say you still can't shoot yourself in the foot with Angular (especially with something like ng-repeat). There are ways to code an Angular app with an eye on memory / performance, and there are ways to do the opposite, but I don't feel like the framework itself introduces significant overhead.
- onehp 13y agoIt seemed it was detached DOM elements that were causing most of the problems. We tried profiling with the Chrome dev tools but found it very difficult to pinpoint where to start looking from the thousands of elements generated every-time we repeated our workflow. In the end we looked at the bottom line memory consumption and experimented until we saw reductions. We found using things like ng-show instead of ui-if, essentially preloading the partials and switching between them instead of reloading everytime, saved us enough memory to make the system viable.
- sgrove 13y agoWe've had similar problems before (outside of angular), and the lack of visibility and tooling is horrendous. However, at Google I/O they demoed the new object allocation tracker, which seems like a vast, vast improvement. Highly recommended for figuring out where memory is leaking and what code is causing it. Here's the session: https://www.youtube.com/watch?feature=player_embedded&v=x6qe_kVaBpg&t=24m10s https://www.youtube.com/watch?feature=player_embedded&v=... Still pretty primitive, but progress at least.
- michaelw 13y agoI'd add a few more thoughts. Keep your controllers lean and mean. Put more of the UI logic into services. This makes testing a lot easier. Only use routing ($route, $routeProvider) if your app has very little UI state and could reasonably thought of as several totally independent pages. I switched to managing $location.path() explicitly and haven't looked back. Embrace promises throughout your app. Angular templates can now render promises naturally but I've found that I prefer to be more explicit: $http.get(url).then(function(response) { $scope.something = response.data; }, function(error) { $scope.$emit('error', error); }); Wrapping jquery widgets in directives often results in more code than just doing it yourself. Obviously this increases your maintenance surface area but typically less than you would expect. The Angular Bootstrap project is trying to create directives that avoid jquery and could be bound (with different templates) to other UI frameworks. What I really want is a core set of UI widget directives and then separate (bootstrap or foundation inspired or not) CSS libraries for styling them.
- joelhooks 13y agoreally good points. We were "promise shy" and I'm now completely sold and in love with them. We actually use a Command implementation that I ported, which has been really handy for leaning up the controllers, plus they aren't stateful so they are always available. https://github.com/joelhooks/js-command-center https://github.com/joelhooks/js-command-center.
- gizzlon 13y agoTook his advice and opened up a random angular source file. Found this fun, little snippet: // String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish // locale, for this reason we need to detect this case and redefine lowercase/uppercase methods // with correct but slower alternatives. if ('i' !== 'I'.toLowerCase()) { lowercase = manualLowercase; uppercase = manualUppercase; } Looks like Angular is more battle-tested than I would expect..
- acdha 13y agoThat's actually wrong unless that i/I code is strictly internal data which is never shown to a human. Where was the snippet from?
- gizzlon 13y agoWhy is that? https://github.com/angular/angular.js/blob/master/src/Angular.js#L41 https://github.com/angular/angular.js/blob/master/src/Angula...
- acdha 13y agoIn Turkish, "i" uppercases to "İ" (note the dot) - there's a separate undotted lowercase "ı" which becomes "I": http://www.i18nguy.com/unicode/turkish-i18n.html http://www.i18nguy.com/unicode/turkish-i18n.html So basically if your goal is for "i".upperCase() to produce something which goes to another program (e.g. an API call), the Angular code is correct. If it's going to be displayed to humans, it's wrong. The documentation at http://docs.angularjs.org/api/angular.uppercase http://docs.angularjs.org/api/angular.uppercase should probably specify that this cannot be used for user content.
- iso8859-1 13y agoIt's a weird comment because the definition of "correct" is not specified. Is it a workaround for a bug in Unicode or a bug in its implementation?
- deleted 13y ago
- abrkn 13y agoI used to have a problem, so I thought to use AngularJS. Now I have a ProblemDirectiveFactory. http://stackoverflow.com/a/15253892/521834 http://stackoverflow.com/a/15253892/521834 Show me any code that cannot be written faster and shorter using only jQuery, Underscore templates and a CommonJS compiler. Does not exist. You are writing enormous amounts of glue code to please AngularJS and getting lost in your obsession with tools, imagined reusability and over-complicated testing procedures.
- joelhooks 13y agoStrong assumptions!
- chaddeshon 13y agoSometimes it is smarter for the short and long term just to right a little jQuery in your controller. You are right, don't worry about reusability until you actually reuse something for the 3rd time. If you are going to be doing something a lot (capitalizing the first letter in your example), then I think writing the filter does save you in the long run. Writing the filter doesn't seem worth it when you project is small. When you project gets big, and there are little one off jQuery statements everywhere, it gets unmanageable. The filter allows you to look at your template and immediately know why that word is being capitalized. With jQuery, a year from now you won't remember why/how it is being capitalized, and you'll be grepping for ids and class names.
- arcatek 13y agoAnd when you will leave your enterprise, your code won't be maintainable anymore because the next developers will have no idea about the architecture of your application. Then someday someone will say "well ... nobody understand this code anymore ... let's get ride it, guys. I guess it's time for feature freeze.". Of course, we're talking about some size of application here. If you just want to make a todo list, jQuery is fine. But when dealing with a potentially huge codebase, it is good to enforce practices.
- don_draper 13y agoAngular helps you organize and test your code. How did you test your 50+ onclick functions? Did someone come after you to do maintenance and agree the jQuery was the way to go?
- dustingetz 13y agodear bloggers and commenters, you really need to qualify "large". "Large" probably means something between 10k LOC and 1M LOC and the approach to coding at either end if this spectrum is vastly different. For example, I'm at the 50k mark on the frontend and I found angular's basic building blocks to be too restrictive in terms of organizing things into reusable components. I had to answer questions like "can views do I/O", "does a view own his model", "how deeply should views nest", "should my models be tree-like or rectangular", "can my contracted designer write arbitrary markup with arbitrary UI widgets or does the framework not like that". Angular's way of doing controllers with dependency injection got in my way of answering these questions. I would love to read someone's opinions on this, especially if I'm wrong, but nobody (including me) has time to write a well thought out essay on this.
- joelhooks 13y agoI haven't actually taken the time to get the metrics, but probably in the neighborhood of 50k.
- jacques_chester 13y agoTry sloccount or cloc: http://www.dwheeler.com/sloccount/ http://www.dwheeler.com/sloccount/ http://cloc.sourceforge.net/ http://cloc.sourceforge.net/ Both are in all the major repos -- apt, yum, ports, brew etc.
- chaddeshon 13y agoI agree. I think when people say "large" they mean that spaghetti jQuery code wasn't working anymore. I was able to get to 10K LOC with a well thought out hombrew jQuery framework (Angular, Backbone, etc weren't available when we started), and it was still fairly maintainable. As I approach 20K lines of code it is getting out of hand. I would like to switch the project o Angular. I'd love to hear more about the problems/questions you are having. Have you found answers to some? Here's what I have come up with. How does it compare to what you are doing? "can views do I/O" I've put file I/O in a controller. If I would have needed to share it across multiple pages, then I would have put it in a service "does a view own his model" I have model classes defined outside of Angular. Services access my API to create new objects (of types defined by my models). Controllers request data from the services. The service figures out if it already has the data or if it needs to call the API. "how deeply should views nest" I often wonder how much I should be breaking up my views into smaller view. For the moment, I only create "subviews" if I am going to reuse the subview in another view. This has lead to some large template files. I may need to reconsider if they get much bigger. "should my models be tree-like or rectangular" I don't understand what you are asking. What's the difference? "can my contracted designer write arbitrary markup with arbitrary UI widgets or does the framework not like that" Again, I'm not sure what you are getting at. Arbitrary markup and UI widgets as apposed to what?
- jlongster 13y agoI have a hard time adopting frameworks because of the all-or-nothing aspect of them. If you use Angular, you have to use their templating language, right? I know that they do a lot of powerful things with it, but honestly it's difficult for me to throw away all of my current tools. It's just too much of a jump. There's so much I love about libraries like angular and ember, but I'd love it if someone was working on a way to allow additional templating languages. I don't know how it would work, but you could possible compile other templates down to angular templates. I've been thinking of a way to convert simple templates in angular's style, so that you can do all the cool auto-updating features. If there was a standard for this, templates like mustache, etc could compile a subset down to it. Disclaimer: I'm the creator of nunjucks https://github.com/jlongster/nunjucks https://github.com/jlongster/nunjucks.
- deleted 13y ago[deleted]
- joelhooks 13y agoI've used Jade and Angular in the past. Angular allows you to change the bracket notation to something custom, which helps avoid conflicts. For the type of app I've been working on, the all-or-nothing hasn't been a real hindrance, but Angular is definitely a Framework and not so much a modular toolkit (like Backbone, for instance, which I would say is generally a better choice if you want to build something "custom")
- nahname 13y agoThe way most developers work with JavaScript (especially jQuery) is fundamentally broken and untestable. This was one of the most difficult things I fought with when using backbone and introducing developers to backbone. You can work with it the way that you know, but that is the hard way. It will make team scaling more difficult than it needs to be and you will be missing out on what the majority of the framework does for you. This is a major reason why I am coming around to Angular. Take away jQuery and developers have to stop and think. It makes it difficult to rush ahead chaining dozens of callbacks and tightly coupling their code to the DOM, in the familiar jQuery way. This, above all else, is what allows you to create a single page web application. The rest is just gravy on top.
- jasallen 13y agoI think people who've worked a lot on 'classic' web pages misunderstand some things. Angular and other MV* frameworks are not out to replace or add on to JQuery or Underscore or any other JS toolkits. They are out to replace Rails and ASP.Net and Zend. Or at least large parts of what those apps used to handle. You will still use all your JS tools, it is your server tools that will get lighter-weight as page flow and layout are (exclusively sometimes) moved to the client. Ideally your server logic returns only JSON and otherwise your server is a file host for HTML, JS, CSS. Edit: my comment is in response to some other comments I've seen, not the OP.
- taternuts 13y agoMost angular diehards really try to use as little jQuery as possible, since most the times it's not needed to do what you want to do
- jasallen 13y agoI guess I'd say most of us try to encapsulate it in directives or use the scopes that are there for us, but even Angular uses JQuery or its own jqLite under the hood. edit to add: In fact, on further reflection, Angular passes JQuery or JQLite objects to the Link functions of custom directives, so it's actually kind of opinionated in favor of using JQuery, it just adds some extra layers of abstraction to ease some things.
- zenocon 13y agoAngular's jQLite does the job just fine. If you're writing directives, and not putting all your DOM manipulation in the controller, then jQuery is no longer necessary / useful IMHO. Why pull it in at all? The only thing it lacks is DOM wide selectors, but again, if you're writing a directive, you're passed the element, and you can do selectors on that element and it's children, which is all you should need -- otherwise, it seems the abstraction has started to leak, and requires re-consideration for your design. I don't use any jQuery transitions / animations. Angular's own $http service does all the Ajax I need. YMMV, but I like the fact that I can avoid library bloat by learning one useful toolkit very well, and applying it effectively...and I happen to like all of its other features.
- metaphorm 13y agothanks for the post. this was a good read. I'm about to start work on a medium sized Angular project and this kind of thing is very helpful. I didn't see any mention of your backend for the project, but I did get the impression it was something Java (why else would you be using Maven?). I'm looking to be writing angular templates on top of a django backend (supplying a RESTful api for data access). I'd love to read more about integrating Angular with RESTful backends.
- chaddeshon 13y agoI really think AngularJS with Firebase is the future. Using Firebase makes you app real-time, with no additional development. When you don't have to write any server side code at all, it can really speed things up.
- metaphorm 13y agothanks for the tip. I just checked out their demo page and it looks pretty sweet. I'm mostly still working on applications that have plenty of relational data and server-side data processing, so I don't think Firebase will be of immediate use for me, but I'm definitely impressed. The speed and ease is very nice.
- GeneralMaximus 13y ago> I'd love to read more about integrating Angular with RESTful backends. If your backend exposes a textbook REST interface, integrating it with AngularJS is almost no work at all. $resource is all you need. In case you have one or two non-RESTful endpoints here and there – and honestly, who doesn't? – $http is your friend. In an app I'm working on, I have a front-end built with Angular talking to a Tastypie back-end. Since Tastypie implements all the boring REST CRUD for you automagically, integrating the two took about fifteen minutes total. If there are there any specific questions/issues on your mind, ask away.
- metaphorm 13y agothats great. thanks. I'm still learning about Angular and had been using $http pretty much raw for most of the data fetching. I started to play around with $resource but didn't get very far due to some frustratingly vague documentation on the official site. Do you know of any really good tutorials emphasizing Angular's $resource service?
- don_draper 13y agoWow. Strong opinions on both sides of the debate.
- pmaccart 13y agoOne of the issues I struggled with while toying around with AngularJS was how to load the many scripts (controllers, directives, etc.). Is there any suggested reading out there on how to perform this without just including a bunch of script tags on the page? Or, is this considered more of a build tool problem, where the scripts should all be concatenated, then loaded as a single file?
- smhinsey 13y agoI use require.js for this. There are a number of seed projects out there to get you started, but I suggest not following them too closely. Once you understand the basic technique it's easier to figure out your own organizational structure. My main suggestion is to discard the seed project's suggestions of organizing things into directories like /controllers, etc., in favor of organizing the files around specific screens. This reduces friction when it comes to using things like route resolves, which are a huge pain if you have the routes in a routes.js and the controllers in controllers/MyController.js.
- pmaccart 13y agoThanks -- I had tried going down the requirejs route with all controllers loaded into a 'controllers' module, directives into a 'directives' module, etc., and felt like I was writing way more boilerplate code than should be necessary with a framework like Angular. I'll have to revisit using requirejs with more of a page/functionality-oriented structure.
- camus 13y agoDont use requirejs,it solves very little problems. Have a dev distrib where you pile up js files and templates, and a prod distrib where your files are "merged" into one. Requirejs is a nightmare to use, especially with the angularjs ioc container. Remember you can reopen the same module in different files.
- smhinsey 13y agoYeah, I don't get that approach at all. I started with that, ran into a case where I wanted a route resolve, couldn't figure out how to do it without a huge amount of hassle, and ended up reorganizing around screens. I do still have global services, directives, and filters, but I define them as close to screens as I can and only pull them up to a global scope when necessary. The module-per-screen approach makes a lot of sense from both Angular and Require's perspective, I think. We use the optimizer as well, during our build process, so you can use require to load everything during development and then optimize everything down into a single file later. The optimizer is pretty powerful and supports several different scenarios for doing this.
- cletus 13y agoI too have built a reasonably sized Angular app in the last year [1] and echo a lot of these thoughts. I'll add a few of mine: 1. For CSS, honestly for any project it'd be hard for me not to simply use Bootstrap and be done with it and then do the minimum CSS possible (I say this as someone who has been doing CSS for years). Bootstrap really is the de facto CSS for the modern Web; 2. Organization: I agree the angular-seed project (which I started with and still use) isn't suited to organizing large projects and I agree separating into functional modules is the way to go; 3. Directives are awesome but to get all the two way data binding working requires a fairly deep understanding of how they work (to get the correct combination of scopes, transclusion, etc); 4. Directives also have limits that are sometimes annoying. You still can't generate definition list items with an ng-repeat, for example (a template has to have one top-level element). A solution to this is coming; 5. There's no good way of both just including code and using the parent scope plus some extras. This is done for reasons of code separation but there really is a use case (IMHO) for includes vs imports for templates; 6. $resource has no HTTP PUT method; 7. I'd probably avoid $resource altogether although it looks attractive. Use rich objects [2] instead; 8. Angular allows you to use a bunch of different other frameworks but it doesn't always play completely nice with them. Take the popover in Bootstrap. The way this works is by moving an element around in the DOM. This doesn't lend itself to a "nice" Angular directive (my version at least is kind of a hack). 9. Underscore.js is awesome. Use it; 10. Try to limit yourself to using jqLite that Angular comes with rather than full jQuery. This isn't really possibly with any reasonable part of Bootstrap however; 11. Isolate scopes in directives results some weird and unexpected behaviour. For example, if you reference something with an attribute, it'll work if it's an object (including an array) but won't with a simple value, requiring you to put such values in objects just so the directive can get a reference to it. This tripped me up a few times; 12. Scopes aren't always truly isolated either. For example, you can get tripped up by this if you have two attribute directives on the same element. [1]: for those who follow IO, I am the Tech Lead of the Open Bidder project at Google (http://googleadsdeveloper.blogspot.com/2013/05/announcing-open-bidder-beta-platform.html http://googleadsdeveloper.blogspot.com/2013/05/announcing-op...) [2]: http://stackoverflow.com/a/11850027/18393 http://stackoverflow.com/a/11850027/18393
- jonny_eh 13y ago
- andreypopp 13y agoIf you like directives in Angular.js but use Backbone or simply want something which is not so much opinionated then you might like to take a look at Backbone.ViewDSL[1] which provides data-binding and custom directives for Backbone.View [1]: https://github.com/andreypopp/backbone.viewdsl https://github.com/andreypopp/backbone.viewdsl
- Kiro 13y agoCan someone explain why I should use any of the tools listed in The Build? Why do I need to add that layer of complexity?
- joelhooks 13y agoI added it based on a comment. Yeoman is interesting because it has "rails like" generators. This can be nice on a project of size, for consistency and saving time. Yeoman uses Grunt, which is nice for building, watching, and packaging. Not strictly needed, but very useful and recommended.
- VilleSalonen 13y agoCan anyone point me to real world AngularJS project with a healthy amount of unit and end-to-end tests? I've read the tutorials from official site and elsewhere on the web but they seem to stop after showing how create a controller with mock $http. As a relatively novice JavaScript developer, I'd like to see more comprehensive examples with mock services etc.
- skype 13y agoHi
- skype 13y agoI too have built a reasonably sized Angular app in the last year [1] and echo a lot of these thoughts. I'll add a few of mine: 1. For CSS, honestly for any project it'd be hard for me not to simply use Bootstrap and be done with it and then do the minimum CSS possible (I say this as someone who has been doing CSS for years). Bootstrap really is the de facto CSS for the modern Web; 2. Organization: I agree the angular-seed project (which I started with and still use) isn't suited to organizing large projects and I agree separating into functional modules is the way to go; 3. Directives are awesome but to get all the two way data binding working requires a fairly deep understanding of how they work (to get the correct combination of scopes, transclusion, etc);