LoginSignup
2
2

More than 5 years have passed since last update.

yeomanのangular-generatorで作られたGruntfile.jsはこんな構成になっている

Posted at

ぶっちゃけ全然分からなかったので読み解いてみた。

Gruntfile.jsの中身

use strict

Gruntfile.js
// Generated on 2015-08-27 using generator-angular 0.11.1
'use strict';

今までうまいことやってくれてたがためにバグを産んでたところがエラーとみなされるようになった。参考資料

Globbing

Gruntfile.js
// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

対象ディレクトリを再帰的に検索するか直下のものに限定するか。
{,*/}は、{}内の,で区切られたもののどれかに当てはまるディレクトリを検索する。
'test/spec/{,*/}*.js'であれば、'test/spec/*.js'または'test/spec/*/*.js'を検索する。**は複数のサブディレクトリの再帰検索を示す。参考資料

module.exports

Gruntfile.js
module.exports = function (grunt) {

Gruntfileの内容はすべてこの中に書く。いや、ほんと何も分からないんですよ…。

npmモジュールのロード

Gruntfile.js
  // Load grunt tasks automatically
  require('load-grunt-tasks')(grunt);

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

load-grunt-tasksは、ワイルドカードでgrunt.loadNpmTasksをまとめてくれる。これ自身はデフォルト値を利用してgrunt-*に一致するすべてのNpmTasksをロードしてくれる。参考資料
time-gruntはタスクの実行時間を計測してくれる。参考資料
appConfigは下で読み込むための値。

初期値設定

Gruntfile.js
  // Define the configuration for all the tasks
  grunt.initConfig({

この中に初期化処理を書く。

アプリケーションの設定を読み込み

Gruntfile.js
    // Project settings
    yeoman: appConfig,

上記のappConfigをyeomanというキー値で読み込む。
以下でyeoman.appとか出てきたらこれを参照してるんだと思う。

grunt-contrib-watchの設定

Gruntfile.js
    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'karma']
      },
      styles: {
        files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
        tasks: ['newer:copy:styles', 'autoprefixer']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '.tmp/styles/{,*/}*.css',
          '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

grunt-contrib-watch(github)についての設定。(gruntはプラグインと同じ名称のオブジェクトを設定として読み込む。)
このプラグインは名前の通りファイル監視用プラグインで、filesで指定したディレクトリにファイルの変更があったら察知してtasksに指定したタスクを実行する。
bowerjsはターゲットと言って$grunt watch:bowerというようにコロンつなぎで実行するとこの中に書かれた設定でコマンドが実行される。Grunt公式サイト参照。
たとえばbowerなら、

  • files: ['bower.json'] bower.jsonに変更があったら、
  • tasks: ['wiredep'] wiredep(アプリケーションにbowerプラグインを自動で読み込む)タスクを実行する。

grunt-contrib-connectの設定

Gruntfile.js
    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/styles',
                connect.static('./app/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

grunt-contrib-connect(github)について設定。参考資料
このプラグインはgruntで静的サーバを立ち上げる。
optionsターゲットはconnectタスク共通の設定で、特に他のターゲットで上書きしなければこれが適用される。
optionsは、

  • port: 9000, 9000番ポートを使用し、
  • hostname: 'localhost', localhostをホストに使用し、
  • livereload: 35729 変化の自動読み取りには35729番ポートを使用する。

livereloadでは、

  • open: true, protocol(デフォルトで'http')オプション、hostnameオプション、portオプションを合成してデフォルトブラウザで開いてくれる。openオプション参照。
  • middleware: function (connect) {... よくわかりません。 なんかサーバに配置するものとか決めてるんですかね…違うだろうな…。

jshintの設定

Gruntfile.js
    // Make sure code styles are up to par and there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

jshint(github)についての設定。
このプラグインはJSHintをgruntから実行できる。
以下、オプションの説明。

  • jshintrc 特に設定しなければデフォルトの設定が使用される。今回は'.jshintrc'を指定している。
  • reporter 結果のアウトプットを指定しているようだ。今回は外部プラグインjshint-stylishを使用している。
  • src はそのまま、対象ディレクトリを指定している。ちなみに<%= yeoman.app %>は、公式サンプルどおりGruntfileの他の部分で宣言したオブジェクトの値を流用している。

cleanの設定

Gruntfile.js
    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp'
    },

grunt-contrib-clean(github)の設定。
これは指定したディレクトリ内を掃除してくれる。
設定は簡単なので割愛。多分ドットファイルを対象とするかとか対象のディレクトリはどこか、とか決めているのでしょう。(慢心)

autoprefixerの設定

Gruntfile.js
    // Add vendor prefixed styles
    autoprefixer: {
      options: {
        browsers: ['last 1 version']
      },
      server: {
        options: {
          map: true,
        },
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/styles/'
        }]
      }
    },

grunt-autoprefixer(github)の設定。
これはCSSにベンダープレフィックスを自動でつけてくれる。
今回の設定は以下のことを示している。

  • browsers: ['last 1 version'] browserslistの記法に従って、メジャーなブラウザの最新バージョンを網羅して
  • map: true source mapっていうのを作成するかどうか選べるみたいですが よくわかりません
  • files プラグイン依存ではなく、gruntのファイル指定の方法。公式ドキュメント参照。指定の方法に拡張設定(expand)をすることもできて、それについても公式ドキュメント参照。

wiredepの設定

Gruntfile.js
    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      }
    },

grunt-wiredep(github)についての設定。
指定したHTMLファイルにbowerコンポーネントを読み込むタグを追記してくれる。
たとえばappターゲットなら

  • src: ['<%= yeoman.app %>/index.html'], このアプリケーションのindex.htmlに書き込む。
  • ignorePath: /\.\.\// ただし../は除く。 実はちょっと意味がわかってません

filerevの設定

Gruntfile.js
    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/scripts/{,*/}*.js',
          '<%= yeoman.dist %>/styles/{,*/}*.css',
          '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/styles/fonts/*'
        ]
      }
    },

filerev(github)の設定。
このプラグインはファイルの内容のリビジョンを保管して変更があった時だけキャッシュを更新する。 ちょっとどんな役割かわかってません。

minifiyの設定

Gruntfile.js
    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/images',
          '<%= yeoman.dist %>/styles'
        ]
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/styles/main.css': [
    //         '.tmp/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/images',
          src: '{,*/}*.svg',
          dest: '<%= yeoman.dist %>/images'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true,
          removeOptionalTags: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html', 'views/{,*/}*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

usemin(github)に関する設定。
ファイルの最小化について設定ができるようです。

ng-anotateの設定

Gruntfile.js
    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

grunt-ng-annotate(github)の設定。
AngularJSは変数名を勝手にminifyされると正常に動かなくなってしまうので、それを安全にしようというプラグイン。

cdnifyの設定

Gruntfile.js
    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

cdnify(github)についての設定。静的ファイルをCDNで取得するように変更する?

copyの設定

Gruntfile.js
    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '*.{ico,png,txt}',
            '.htaccess',
            '*.html',
            'views/{,*/}*.html',
            'images/{,*/}*.{webp}',
            'styles/fonts/{,*/}*.*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/images',
          dest: '<%= yeoman.dist %>/images',
          src: ['generated/*']
        }, {
          expand: true,
          cwd: 'bower_components/bootstrap/dist',
          src: 'fonts/*',
          dest: '<%= yeoman.dist %>'
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/styles',
        dest: '.tmp/styles/',
        src: '{,*/}*.css'
      }
    },

grunt-contrib-copy(github)の設定。他のタスクが使用できるように、指定したファイルをコピーするタスク。ファイルを指定したりする動作はautoprefixerの時とおなじ。

concurrentの設定

Gruntfile.js
    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'copy:styles'
      ],
      test: [
        'copy:styles'
      ],
      dist: [
        'copy:styles',
        'imagemin',
        'svgmin'
      ]
    },

grunt-concurrent(github)の設定。
これは処理の重いタスクを並列処理してくれるプラグイン。

karmaの設定

Gruntfile.js
    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    }
  });

grunt-karma(github)の設定。ちなみにkarmaはNodeJS製のテスト実行環境。

タスクの登録

Gruntfile.js
  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'autoprefixer:server',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'autoprefixer',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'autoprefixer',
    'concat',
    'ngAnnotate',
    'copy:dist',
    'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'test',
    'build'
  ]);
};

gruntではgrunt.registerTaskと書くことでコマンドから実行するときの名前を自分で設定できる。複数のタスクをまとめたタスク名も設定できて、それを実行すると指定したすべてのタスクを実行してくれる。

次は

ひと通りは調べられたけど、まだまだ分からないところがたくさんあるので、折に触れて調べよう。
karmaとかjasmineとか、あとgulpもひと通りは知っておきたいなあ。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2