AngularJS開発のフォルダ構成

AngularJS開発でフォルダ構成をどうするか悩んだのでまとめてみました。
さんざん語られている話題ではありますが。。

#部品単位
[こちら](http://qiita.com/tamanyan/items/b40906431638a6d21727)などで紹介いただいている
yeomanを使用するとこんな感じ。


```:yeoman
│  bower.json
│  Gruntfile.js
│  package.json
│  
├─app
│  │  404.html
│  │  bower.json
│  │  favicon.ico
│  │  index.html
│  │  robots.txt
│  ├─bower_components
│  ├─images
│  ├─scripts
│  │  │  app.js
│  │  │  
│  │  └─controllers
│  │          about.js
│  │          main.js
│  │          
│  ├─styles
│  │      main.css
│  │      
│  └─views
│          about.html
│          main.html
…
```
コントローラやテンプレートと部品ごとに分割しています。
スッキリしているし、フォルダの中が同じ部品だとわかっているので、後々置換などが発生しても楽そうです。

#ユースケース単位
[Mastering Web Application Development with AngularJS](http://www.amazon.co.jp/Mastering-Web-Application-Development-AngularJS-ebook/dp/B00EQ67J30)（Kindle安い！2014/11/5で1,801円）で紹介されているパターンだとこんな感じ。ちょっと長めに引用。
ソースは[こちら](https://github.com/angular-app/angular-app)です。

```:usecase
├─client
│  │  .gitignore
│  │  gruntFile.js
│  │  package.json
│  │  
│  ├─dist
│  ├─src
│  │  │  index.html
│  │  │  
│  │  ├─app
│  │  │  │  app.js
│  │  │  │  header.tpl.html
│  │  │  │  notifications.tpl.html
│  │  │  │  
│  │  │  ├─admin
│  │  │  │  │  admin.js
│  │  │  │  │  
│  │  │  │  ├─projects
│  │  │  │  │      admin-projects.js
│  │  │  │  │      projects-edit.tpl.html
│  │  │  │  │      projects-list.tpl.html
│  │  │  │  │      
│  │  │  │  └─users
│  │  │  │          admin-users-edit.js
│  │  │  │          admin-users-list.js
│  │  │  │          admin-users.js
│  │  │  │          uniqueEmail.js
│  │  │  │          users-edit.tpl.html
│  │  │  │          users-list.tpl.html
│  │  │  │          validateEquals.js
│  │  │  │          
│  │  │  ├─dashboard
│  │  │  │      dashboard.js
│  │  │  │      dashboard.tpl.html
│  │  │  │      
│  │  │  ├─projects
│  │  │  │  │  projects-list.tpl.html
│  │  │  │  │  projects.js
│  │  │  │  │  
│  │  │  │  ├─productbacklog
│  │  │  │  │      productbacklog-edit.tpl.html
│  │  │  │  │      productbacklog-list.tpl.html
│  │  │  │  │      productbacklog.js
│  │  │  │  │      
│  │  │  │  └─sprints
│  │  │  │      │  sprints-edit.tpl.html
│  │  │  │      │  sprints-list.tpl.html
│  │  │  │      │  sprints.js
│  │  │  │      │  
│  │  │  │      └─tasks
│  │  │  │              tasks-edit.tpl.html
│  │  │  │              tasks-list.tpl.html
│  │  │  │              tasks.js
│  │  │  │              
│  │  │  └─projectsinfo
│  │  │          list.tpl.html
│  │  │          projectsinfo.js
│  │  │          
│  │  ├─assets
│  │  │  │  favicon.ico
│  │  │  │  
│  │  │  └─img
│  │  │          glyphicons-halflings-white.png
│  │  │          glyphicons-halflings.png
│  │  │          spinner.gif
│  │  │          
│  │  ├─common
│  │  │  ├─directives
│  │  │  │  │  gravatar.js
│  │  │  │  │  modal.js
│  │  │  │  │  
│  │  │  │  └─crud
│  │  │  │          crud.js
│  │  │  │          crudButtons.js
│  │  │  │          edit.js
│  │  │  │          
│  │  │  ├─resources
│  │  │  │      backlog.js
│  │  │  │      projects.js
│  │  │  │      sprints.js
│  │  │  │      tasks.js
│  │  │  │      users.js
│  │  │  │      
│  │  │  ├─security
│  │  │  │  │  authorization.js
│  │  │  │  │  index.js
│  │  │  │  │  interceptor.js
│  │  │  │  │  retryQueue.js
│  │  │  │  │  security.js
│  │  │  │  │  
│  │  │  │  └─login
│  │  │  │          form.tpl.html
│  │  │  │          login.js
│  │  │  │          LoginFormController.js
│  │  │  │          toolbar.js
│  │  │  │          toolbar.tpl.html
│  │  │  │          
│  │  │  └─services
│  │  │          breadcrumbs.js
│  │  │          crud.js
│  │  │          crudRouteProvider.js
│  │  │          exceptionHandler.js
│  │  │          httpRequestTracker.js
│  │  │          i18nNotifications.js
│  │  │          localizedMessages.js
│  │  │          notifications.js
│  │  │          
│  │  └─less
│  │          stylesheet.less
│  │          variables.less

```
コントローラとテンプレートが同一フォルダで、サービスやディレクティブは共通部品として配置されています。
確かに、コントローラとテンプレートが一緒のほうが開発しやすいですね。
上記書籍にはこの構成について、結構なページ数の解説があって、これだけでも良心的だなあと思います。

上記構成でのgruntoの抜粋を以下に。

```js:gruntFile.js
module.exports = function (grunt) {

~略~

  // Project configuration.
  grunt.initConfig({
    distdir: 'dist',
    pkg: grunt.file.readJSON('package.json'),
    banner:
    '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
    '<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
    ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
    ' * Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %>\n */\n',
    src: {
      js: ['src/**/*.js'],
      jsTpl: ['<%= distdir %>/templates/**/*.js'],
      specs: ['test/**/*.spec.js'],
      scenarios: ['test/**/*.scenario.js'],
      html: ['src/index.html'],
      tpl: {
        app: ['src/app/**/*.tpl.html'],
        common: ['src/common/**/*.tpl.html']
      },
      less: ['src/less/stylesheet.less'], // recess:build doesn't accept ** in its file patterns
      lessWatch: ['src/less/**/*.less']
    },

~略~

    html2js: {
      app: {
        options: {
          base: 'src/app'
        },
        src: ['<%= src.tpl.app %>'],
        dest: '<%= distdir %>/templates/app.js',
        module: 'templates.app'
      },
      common: {
        options: {
          base: 'src/common'
        },
        src: ['<%= src.tpl.common %>'],
        dest: '<%= distdir %>/templates/common.js',
        module: 'templates.common'
      }
    },
    concat:{
      dist:{
        options: {
          banner: "<%= banner %>"
        },
        src:['<%= src.js %>', '<%= src.jsTpl %>'],
        dest:'<%= distdir %>/<%= pkg.name %>.js'
      },
      index: {
        src: ['src/index.html'],
        dest: '<%= distdir %>/index.html',
        options: {
          process: true
        }
      },
~略~

    },

~略~

```
html2jsで「src/app/\*\*/\*.tpl.html」、「src/common/\*\*/\*.tpl.html」配下のhtmlをJS化、
モジュール単位のJSファイルをconcatで「<%= pkg.name %>.js」にまとめています。
AngularJSで書かれている分にはファイル結合の順序は問われないと。

index.htmlのビルド前後の差分は以下。

```html:index.html(ビルド前)
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
  <link rel="stylesheet" type="text/css" href="/static/<%= grunt.config.get('pkg.name') %>.css"/>
  <script type="text/javascript" src="/static/jquery.js"></script>
  <script type="text/javascript" src="/static/angular.js"></script>
  <script type="text/javascript" src="/static/mongolab.js"></script>
  <script type="text/javascript" src="/static/bootstrap.js"></script>
  <script type="text/javascript" src="/static/<%= grunt.config.get('pkg.name') %>.js"></script>
</head>
~略~
```

```html:index.html(ビルド後)
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
  <link rel="stylesheet" type="text/css" href=/angular-app.css"/>
  <script type="text/javascript" src="jquery.js"></script>
  <script type="text/javascript" src="angular.js"></script>
  <script type="text/javascript" src="mongolab.js"></script>
  <script type="text/javascript" src="bootstrap.js"></script>
  <script type="text/javascript" src="angular-app.js"></script>
</head>
~略~
```

どちらもよいですが、個人的にはユースケース単位で分割したほうが好みでした。