Thursday, February 13, 2014

An AngularJS Style Guide and Best Practice for App Structure

Want to know more about AngularJS Best Practices, as we use them at Google?


UPDATE 4/19/2015: The most current and detailed Angular Style Guide is the community-driven effort led by John Papa and Todd Motto, which you can find at https://github.com/johnpapa/angular-styleguide. Please use this instead of the one mentioned below.

You can now find a published copy of Google's AngularJS Style guide at https://google-styleguide.googlecode.com/svn/trunk/angularjs-google-style.html. While this documents how we use AngularJS in production code at Google, you'll notice that the style guide is heavily biased towards JSCompiler optimizations and the needs of large code bases. We don't think this makes sense for all projects that use AngularJS, and we'd love to see our community of developers come up with a more general Style that's applicable to AngularJS projects large and small. Interested in helping or leading this project? Sign up here, and choose "Style Guide for Angular" and we'll be in touch.

We've also published some new Best Practice Recommendations for Angular App Structure. One of our goals is to come up with a recommendation that meets the needs of both large and small app developers, so that we can start developing tooling that makes development easier. If you're not using this recommended structure yet, don't worry. It's fine to keep doing what you're doing. At some point, we hope the efficiency gain of having more developer tools will make it worth your time to convert over.

31 comments:

  1. The new app structure recommendations make a lot of sense, especially from the perspective of modularity and code reuse. Has anyone taken up the effort to build a yeoman generator that matches?

    ReplyDelete
    Replies
    1. I second the recommendation for a new yeoman generator that matches the component orientation of the new app structure. This should be a priority for all yeoman scaffolds to imprint best practices. In addition the component orientation better matches bower components. All MVC's fall into the MVC directory trap. Separation of concerns does not mean separation of common sense.

      Delete
    2. I think the https://github.com/cgross/generator-cg-angular have some of the concepts.

      Delete
    3. a generator with a 'grunt or gulp option'.... anyone? :)

      Delete
    4. We built a generator (https://github.com/lefos987/generator-ghurt) which follows a lot of the concepts. We are in the process of improving it to add tests in the same folder as source and add gulp as an alternative build tool.
      Hope it will help :-)

      Delete
    5. An effort to build a Mimosa skeleton is welcomed too.

      Delete
  2. What do you think of the app structure I created in http://radian.io?

    ReplyDelete
    Replies
    1. I think it takes a lot of pain and blood to find and read the app structure you are referring to.

      Delete
  3. I'm already following this one: https://github.com/mgechev/angularjs-style-guide

    ReplyDelete
    Replies
    1. I like that guy's structures but his proxy nomenclature refers to page1 and so on. Do any of us think as I do that we need to stop referring to what is being displayed on the screen as "pages?"

      S(ingle) P(age) A(pplications) have one "page" but many screens, many windows or many views when we get literal about nomenclature and what is really occuring. If we are going to get this way about structure per se should we not be referring to results structurally as well so we all know what the hell each of us is referring to when writing or speaking with one another?

      And speaking of "referring," the dog already ran away from home on this subject. Since we'll be spelling HTTP_REFERER incorrectly the rest of our lives perhaps we might as well pretend by referring to pages when they are not pages any more and just call it a day.

      Delete
  4. We can say that Google is a great link storage. It provides best removals services. I like this services. Thanks for this information.

    ReplyDelete
  5. Thanks, I'm starting to restructure my AngularJS apps to meet these guidelines. Do you plan on adding variable naming conventions at some point as well?

    For example, should all controllers be named "FooCtrl", should my main application module be "app" or "foo"? Should child modules be "foo.bar" or just "bar"?

    And preference of naming 3rd party libraries folder, "lib" or "vendor" folder? Personally I prefer vendor which is almost always at the bottom of my root folder due to naming. Something about a short name "lib" in the middle of my root bothers me...

    I've also got several LESS files and images used across the application. I've combined these files into an assets folder, "assets/les/.." and "assets/img/.." (only for shared images).

    ReplyDelete
  6. As there is no big-ass taxonomy of the entire internet there is no silver bullet file structure. As today's IDEs are able to refabricate the whole code within minutes what is the point? The project file structure is managed by the senior developer based on his/her experience and it is his/her responsibility. There is a zillion variables to be considered (Bower, RequireJS, Angular UI with or without templates, size and structure of the team, etc.).
    If anybody wants to influence other peoples' filestructure (why?) he/she should offer the community a good lookin Yo generator or Seed v.3.00 that make sense.

    ReplyDelete
  7. Hi!

    Why do you consequently define stuff in the Global Scope in all the tutorials? Isn't that bad practice? Shouldn't controllers and modules simply be declared using the angular.module('myModule').controller('Home', ['$scope', function($scope) {}]); syntax? That way only angular is defined on the global scope, and everything is fine and dandy? :)

    ReplyDelete
  8. How do you deal with templateUrl values of directives (and $modals)?
    Is there any other solution than to specify the complete path to the HTML?
    That kind of defeats the purpose of having js and html in the same folder and breaks encapsulation of the component.

    ReplyDelete
    Replies
    1. Hey Stephen,
      To solve this problem, I wrap each of my templates in a ng-template script tag to give it a unique name that matches the state. I then insert all the templates into index.html using a Grunt htmlbuild task. It works well for making the code very modular.

      Delete
  9. These are great! I've also written up some of my structuring guidelines I follow here: http://www.johnpapa.net/angular-app-structuring-guidelines/

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. I can't spell Ctrl without a typo and for me it doesn't read well. I spell out Controller as I got into the habit of doing when I adopted ASP.NET Web Forms conventions, i.e. EmailValidator, SaveButton and so on.

    That said Google also wants to adopt a file naming convention for other file types [1]. I think its a good idea if we can generate consensus. When developing an RSS Feed Generator I devised what I called a "dotted notation file naming convention a similar form of which was later adopted by Android developers who adopted the dotted naming convention such as foo.bar.some.domain.com.

    I am not saying I devised and Android adopted what I created but I am saying common sense, frugality and expediency can often be plucked out of the realm of ideas by like minds.

    Neither files nor objects ever sorted together when using our ASP.NET Web Forms naming convention. That's why I devised and adopted a dotted notation convention which I am thinking about implementing with AngularJS (AJS).

    A dotted file naming convention is self-documenting, is easy to read, files sort together as groups of items and file names are easy to take apart do stuff with and then put back together with code if and when needed, i.e. split on delineators and then tell me how many files have been written for managing blood pressure in a healthcare app for example. Then take all of those files identified by name and context and do something else with them.

    I tend to approach structure using objectified references (8+ years brick and mortar architecture) and will have a directory named BloodPressure for example. Within that objectified reference I will locate controllers and other such AJS files. Here's what I am thinking from an AJS dotted file name perspective that is consistent with ASP.NET Web Form conventions....

    BloodPressure/
    directive.record-blood-pressure.js
    directive.chart-blood-pressure.js
    ...
    service.record-blood-pressure.js
    service.chart-blood-pressure.js
    ...
    I only perceive an upside adopting a snake case dotted filename convention and ask if we can generate some consensus using this convention. Some of you will have ideas about how to reconcile when AJS or expediency suggests putting files that are related to a specific objectified reference in a different directory.

    [1] https://docs.google.com/document/d/1XXMvReO8-Awi1EZXAXS4PzDzdNvV6pGcuaF4Q9821Es/pub

    ReplyDelete
  12. I wonder how would the broadcast work if the we have different modules?

    Currently the only way to communicate between controllers are using the $rootScope.$broadcast()
    But my current assumption in my code is that all controllers are within the same module.

    I do understand the purpose of division of modules but ultimately we may have needs to "speak" with other modules and their respective controllers. What would be a better styling to $broadcast into different modules?

    ReplyDelete
  13. Thank you for making this proposal public. I'm excited to see where this standard can take us. Two quick requests:

    1) The folder structure is actually really hard to read in the proposal. There has been some confusion in my organization as to whether a sub-section is a peer to components or a child of components. I know from reading the docs that it is a sibling, but the pictures are confusing and engineers tend to look at pictures. It would help if you could use spacing characters to represent depth like:
    app/
    | components/
    | | some-component/
    | subsection1/
    | | subsection1.js
    etc.

    2) The example using the angular-phonecat app from the original tutorial was very helpful. I was just confused about one thing. What would be the contents for the new file created at app/components/phonecat/phonecat.js? What would be an example? The proposal says it's a "new file to contain the module routing".... AND will the tutorial be rewritten when this is no longer just a proposal to be the example structure app?

    Thanks!

    ReplyDelete
  14. I was using generator-angular for my current, not-so-small project and decided to apply this proposal - it looks much better now. I'm using sass and my only confusion is where should I put my shared styles? F.e. I have a navigation.scss which is imported by app/app.scss. Should i create "styles" directory near my. app.js? How do i distinguish it form my subsections directories? And second question: if my scss files are imported in app.scss, should components/some-directive/some-directive.scss be "some-directive.scss" or "_some-directive.scss" ?

    ReplyDelete
  15. So.. I have some concerns about recommending controller == class.
    Would love to stand corrected... see: http://stackoverflow.com/questions/23250420/angular-style-guide-with-coffeescript

    ReplyDelete
  16. I am very much +1 for the proposed structure in the best-practices doc. Nice work. I think another best practice would be if the best practice doc included a changelog :-). (And a way to subscribe for updates?!) I expect it'll develop over time, and I'd like to know what changed when.

    ReplyDelete
  17. This comment has been removed by the author.

    ReplyDelete
  18. A lot of great points in these resources. I've read a bunch of article about the group-by-folder/feature/module debate, and for me - this was the easiest to digest: https://medium.com/opinionated-angularjs/9f01b594bf06 . Gonna try to follow that article's lead, and look at these Google guides for some fine tuning advice. Thanks!

    ReplyDelete
  19. Any thoughts about the backend? I realize these two things are separate, but if you're developing a feature (and I completely agree with file organization by feature), then you're going to be working on some frontend files and some backend files at the same time. I think that means at least that the testing and building parts should be coordinated and organized based on best practices. Maybe all it would take is putting a grunt file somewhere that's in neither the frontend nor backend tree and have it refer to files in each. The generators I have seen don't do that as far as I can tell. I'm new to this so any correction to my understanding is welcome.

    ReplyDelete
  20. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Amazing comparison! And yes, we feel modular is the way to go.

      Delete
  21. Here's a better link to my comparison of Angular.JS app starters. I'll discuss my conclusions, hurdles and progress building my first Angular.JS app there too.
    http://www.dancancro.com/comparison-of-angularjs-application-starters/

    ReplyDelete

Note: Only a member of this blog may post a comment.