yeoman, grunt, bowerで静的サイト構築(第五回)

yeoman, grunt, bowerで静的サイト構築(第四回)の続き

今回はデプロイの処理の流れを追ってみたいと思います。処理を追うことで、gruntのタスクに関する理解が深まると思います。

「-v」オプションを付けて、より詳細な動作ログを出力して確認します。

$ grunt build -v

さっそく、上から順に見ていきます。

Registering Gruntfile tasks

Initializing
Command-line options: --verbose

Reading "Gruntfile.js" Gruntfile...OK

Registering Gruntfile tasks.

Registering "grunt-contrib-copy" local Npm module tasks.
Reading /app/dev/mobile/node_modules/grunt-contrib-copy/package.json...OK
Parsing /app/dev/mobile/node_modules/grunt-contrib-copy/package.json...OK
Loading "copy.js" tasks...OK
+ copy

Registering "grunt-contrib-concat" local Npm module tasks.
Reading /app/dev/mobile/node_modules/grunt-contrib-concat/package.json...OK
Parsing /app/dev/mobile/node_modules/grunt-contrib-concat/package.json...OK
Loading "concat.js" tasks...OK
+ concat

Gruntfile.js を読み込んで、各モジュールのタスクの読み込みを行っているようです。

clean

Running "clean:dist" (clean) task
Verifying property clean.dist exists in config...OK
Files: .tmp
Options: force=false
Options: force=false
Cleaning ".tmp"...Deleting .tmp...OK
OK

.tmpのディレクトリを削除しています。

.tmpにはcoffeeスクリプトやsassなどのコンパイル済みファイル(js, cssなど)を配置するように、各コンパイルタスクとして設定されています。

リコンパイルするので、作業ディレクトリ(.tmp)をきれいに掃除しているのです。

usemin

Running "useminPrepare" task

Running "useminPrepare:html" (useminPrepare) task
Verifying property useminPrepare.html exists in config...OK
Files: app/index.html -> html
Options: dest="dist"
Going through app/index.html to update the config
Looking for build script HTML comment blocks
Reading app/index.html...OK

Found a block:
        <!-- build:js scripts/vendor/modernizr.js -->
        <script src="bower_components/modernizr/modernizr.js"></script>
        <!-- endbuild -->
Updating config with the following assets:
    - app/bower_components/modernizr/modernizr.js

Found a block:
        <!-- build:js scripts/main.js -->
        <script src="bower_components/jquery/jquery.js"></script>
        <script src="scripts/main.js"></script>
        <!-- endbuild -->
Updating config with the following assets:
    - app/bower_components/jquery/jquery.js
    - app/scripts/main.js

usemin関連のタスクが実行されています。

useminはuseminPrepare, imagemin, svgmin, cssmin, htmlmin, rev, concat, uglifyなどが関連性を持って実行されるので、動作を理解するのが大変かもしれません。

useminPrepare

app/index.htmlを読んで、

<!-- build -->
<!-- endbuild -->

のブロックの内容を取得しています。

これはブロック内に記載したjs, cssを、指定したファイルに出力するためのタグです。

つまり、ファイルマッピング情報を生成しているのです。

Configuration is now:

  cssmin:
  { dist: 
   { files: 
      { '<%= yeoman.dist %>/styles/main.css': 
         [ '.tmp/styles/{,*/}*.css',
           'app/styles/{,*/}*.css' ] } } }

  concat:
  { 'dist/scripts/vendor/modernizr.js': [ 'app/bower_components/modernizr/modernizr.js' ],
  'dist/scripts/main.js': 
   [ 'app/bower_components/jquery/jquery.js',
     'app/scripts/main.js' ],
  'dist/scripts/coffee.js': [ '.tmp/scripts/hello.js' ],
  'dist/scripts/async-local-storage.js': 
   [ 'app/scripts/async.localStorage.js',
     'app/scripts/async.localStorage.examples.js' ],
  'dist/scripts/fullscreensnippet.js': [ 'app/scripts/fullscreensnippet.js' ],
  'dist/scripts/fastclick.js': 
   [ 'app/scripts/fastclick.js',
     'app/scripts/fastclick.example.js' ] }

  uglify:
  { 'dist/scripts/vendor/modernizr.js': 'dist/scripts/vendor/modernizr.js',
  'dist/scripts/main.js': 'dist/scripts/main.js',
  'dist/scripts/coffee.js': 'dist/scripts/coffee.js',
  'dist/scripts/async-local-storage.js': 'dist/scripts/async-local-storage.js',
  'dist/scripts/fullscreensnippet.js': 'dist/scripts/fullscreensnippet.js',
  'dist/scripts/fastclick.js': 'dist/scripts/fastclick.js' }

ファイルマッピング情報ができました。

concurrent

Running "concurrent:dist" (concurrent) task
Verifying property concurrent.dist exists in config...OK
Files: [no src] -> dist
    
    Running "imagemin:dist" (imagemin) task
    
    Done, without errors.
        
    Running "htmlmin:dist" (htmlmin) task
    File dist/404.html created.
    File dist/index.html created.
    
    Done, without errors.
        
    Running "coffee:dist" (coffee) task
    File .tmp/scripts/hello.js created.
    
    Running "coffee:test" (coffee) task
    
    Done, without errors.
        
    Running "svgmin:dist" (svgmin) task
    
    Done, without errors.
        
    Running "compass:dist" (compass) task
    
    Done, without errors.

並列処理で各種リソースのコンパイル及び圧縮処理を行っています。

cssmin

Running "cssmin:dist" (cssmin) task
Verifying property cssmin.dist exists in config...OK
Files: app/styles/main.css -> dist/styles/main.css
Options: report=false
Reading app/styles/main.css...OK
Reading app/styles/main.css...OK
Writing dist/styles/main.css...OK
File dist/styles/main.css created.

app/styles/main.cssを圧縮して、dist/styles/main.cssを生成しています。

responsive_images

Running "responsive_images:dev" (responsive_images) task
Verifying property responsive_images.dev exists in config...OK
Options: separator="-", sizes=[{"width":320},{"width":640},{"width":1024}]

画像を配置していないので、何も動作していませんが、指定した画像サイズで画像を自動生成することができます。

concat

Running "concat:dist/scripts/main.js" (concat) task
Verifying property concat.dist/scripts/main\.js exists in config...OK
Files: app/bower_components/jquery/jquery.js, app/scripts/main.js -> dist/scripts/main.js
Options: separator="\n", banner="", footer="", stripBanners=false, process=false
Reading app/bower_components/jquery/jquery.js...OK
Reading app/scripts/main.js...OK
Writing dist/scripts/main.js...OK
File "dist/scripts/main.js" created.

app/bower_components/jquery/jquery.js, app/scripts/main.js を連結して dist/scripts/main.js を生成しています。

uglify

Running "uglify:dist/scripts/main.js" (uglify) task
Verifying property uglify.dist/scripts/main\.js exists in config...OK
Files: dist/scripts/main.js -> dist/scripts/main.js
Options: banner="", footer="", compress={"warnings":false}, mangle={}, beautify=false, report=false
Minifying with UglifyJS...Reading dist/scripts/main.js...OK
OK
Writing dist/scripts/main.js...OK
File "dist/scripts/main.js" created.

concatタスクで生成したファイルに対し、Minifyを実行し、同一ファイルに出力しています。

copy

Running "copy:dist" (copy) task
Verifying property copy.dist exists in config...OK
Files: app/favicon.ico -> dist/favicon.ico
Files: app/robots.txt -> dist/robots.txt
Files: app/.htaccess -> dist/.htaccess
Options: processContent=false, processContentExclude=[]
Options: processContent=false, processContentExclude=[]
Copying app/favicon.ico -> dist/favicon.ico
Reading app/favicon.ico...OK
Writing dist/favicon.ico...OK
Copying app/robots.txt -> dist/robots.txt
Reading app/robots.txt...OK
Writing dist/robots.txt...OK
Copying app/.htaccess -> dist/.htaccess
Reading app/.htaccess...OK
Writing dist/.htaccess...OK
Copied 3 files

開発環境(app/)のファイルをデプロイ環境(dist/)にコピーしています。

単純なファイルコピーなので、開発環境とデプロイ環境で変更が無いファイルのみが対象です。

rev

Running "rev:dist" (rev) task
Verifying property rev.dist exists in config...OK
Files: dist/scripts/async-local-storage.js, dist/scripts/coffee.js, dist/scripts/fastclick.js, dist/scripts/fullscreensnippet.js, dist/scripts/main.js, dist/scripts/vendor/modernizr.js, dist/styles/main.css -> src
Options: algorithm="md5", length=8
Hashing dist/scripts/main.js...Reading dist/scripts/main.js...OK
OK
>> fc8109b5fd49d06437f53a567e228a50
dist/scripts/main.js >> fc8109b5.main.js

ファイル名にmd5の暗号化文字列を8文字付加して、リネームしています。

js, css, imgなど、ファイルであれば何でもリネームできるようです。

リリース時にブラウザキャッシュを心配する必要がなくなるのはうれしいですね。

usemin

Running "usemin:html" (usemin) task
Verifying property usemin.html exists in config...OK
Files: dist/404.html, dist/index.html -> html
Options: type="html", dirs=["dist"]
Reading dist/404.html...OK
Reading dist/index.html...OK

Processing as HTML - dist/index.html
Update the HTML to reference our concat/min/revved script files
<script src="scripts/vendor/modernizr.js" changed to <script src="scripts/vendor/d7100892.modernizr.js"
<script src="scripts/main.js" changed to <script src="scripts/fc8109b5.main.js"
<script src="scripts/coffee.js" changed to <script src="scripts/3431b5a9.coffee.js"
<script src="scripts/async-local-storage.js" changed to <script src="scripts/107b4b1c.async-local-storage.js"
<script src="scripts/fullscreensnippet.js" changed to <script src="scripts/f4dff991.fullscreensnippet.js"
<script src="scripts/fastclick.js" changed to <script src="scripts/4a20a196.fastclick.js"
Update the HTML with the new css filenames
<link rel="stylesheet" href="styles/main.css" changed to <link rel="stylesheet" href="styles/6bad6e7f.main.css"
Update the HTML with the new img filenames
Update the HTML with data-main tags
Update the HTML with the data tags
Update the HTML with background imgs, case there is some inline style
Update the HTML with anchors images
Update the HTML with reference in input
Writing dist/index.html...OK

各処理の総仕上げです。

ファイル連結・圧縮などを経て、動的に生成された各ファイルの呼び出し箇所に対し、自動でファイル名の置換が行われます。


いかがでしたでしょうか?

Gruntfile.jsの設定と各モジュールの記法に従うだけで、デプロイに必要な様々なタスクを自動化できているのが理解できると思います。

自分でgrunt buildを実行して、デプロイ後の各ファイルを中身を再確認してみましょう。

衝撃と感動を受けると思いますよ!


「yeoman, grunt, bowerで静的サイト構築」としての連載は今回で終わります。

次回以降はgruntの各モジュールにフォーカスしていきたいと思います。