assembleを利用して静的サイトを構築する[yeoman,grunt]

yeomanのgenerator-mobile, generator-webappなどを利用すれば、静的なサイトを実装できる環境は簡単に用意できましたが、assembleを利用することでHTMLの管理・実装に関してさらにすばらしい環境にすることができます。

https://github.com/assemble/assemble/

http://assemble.io/

http://handlebarsjs.com/

assemble

assembleは簡単に言うと、静的サイトを構築するためのフレームワークのようなものです。

実現できることとしては下記が挙げられます。

  • レイアウトテンプレートの利用
  • テンプレートのinclude
  • markdown形式でのHTML記述
  • モックデータの利用

テンプレートエンジンはhandlebarsまたはswigを選択できます。

今回はhandlebarsを利用したいと思います。

install

$ npm i assemble -D

タスクを設定する

handlebars(.hbs)で記述したテンプレートをコンパイルしてHTMLファイルを生成します。

options 設定内容

options.layoutDir  レイアウトテンプレートディレクトリ
options.partials     include用テンプレートディレクトリ/ファイル
options.data         モックデータ用ディレクトリ/ファイル

個別の設定内容

コンパイルする単位毎に設定を行います

watch.livereloadタスクと連携することを踏まえ、ページ単位で設定することをお勧めします。

options.layoutでレイアウトテンプレートを指定し、files.srcでメインコンテンツを記述するファイルを指定します。

grunt/assemble.js

'use strict';

module.exports = function(grunt) {

    grunt.config('assemble', {
        options: {
            layoutdir: 'hbs/layouts',
            partials: ['hbs/includes/**/*.hbs'],
            data: ['mocks/assemble/**/*.yml']
        },
        hoge: {
            options: {
                layout: 'default.hbs'
            },
            files: [{
                expand: true,
                cwd: 'hbs/pages',
                src: 'hoge.hbs',
                dest: '<%= yeoman.app %>'
            }]
        },
        moge: {
            options: {
                layout: 'moge.hbs'
            },
            files: [{
                expand: true,
                cwd: 'hbs/pages',
                src: 'moge.hbs',
                dest: '<%= yeoman.app %>'
            }]
        }
    });

    grunt.loadNpmTasks('assemble');
};

grunt/contlib-watch.js

ページ単位で、当該ページに関連するファイルを監視対象としてassembleのコンパイルタスクを設定します。

また、livereloadの監視対象ファイルとして、コンパイル後に生成されるHTMLファイルを設定します。

'use strict';

var port = require('../port.json');

module.exports = function(grunt) {

    grunt.config('watch', {
        coffee: {
            files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'],
            tasks: ['coffee:dist']
        },
        coffeeTest: {
            files: ['test/spec/{,*/}*.coffee'],
            tasks: ['coffee:test']
        },
        compass: {
            files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'],
            tasks: ['compass:server']
        },
        assembleHoge: {
            files: [
                'hbs/layouts/default.hbs',
                'hbs/pages/hoge.hbs',
                'hbs/includes/footer.hbs'
            ],
            tasks: ['assemble:hoge']
        },
        assembleMoge: {
            files: [
                'hbs/layouts/moge.hbs',
                'hbs/pages/moge.hbs',
                'hbs/includes/footer.hbs'
            ],
            tasks: ['assemble:moge']
        },
        livereload: {
            options: {
                livereload: port.livereload
            },
            files: [
                '<%= yeoman.app %>/*.html',
                '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css',
                '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js',
                '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
            ]
        },
    });

};

モックデータとテンプレートを用意する

モックデータ1(mocks/assemble/data.yml)

foo: bar

モックデータ2(mocks/assemble/baz.yml)

qux: quux

レイアウトテンプレート(hbs/layouts/default.hbs)

※{{}}はhandlebarsの記法です

{{> body}}でfiles.srcに設定したメインコンテンツファイルをincludeできます。

<!DOCTYPE HTML>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
</head>
<body>
This is default layout.
{{> body}}
</body>
</html>

メインコンテンツテンプレート(hbs/pages/hoge.hbs)

1〜3行目はYAML Front Matterを利用してモックデータを定義しています。

hbs/layouts/default.hbsで{{title}}と記述している箇所に、データが代入されます。

{{> footer }}でhbs/includes/footer.hbsをincludeできます。

{{foo}}でmocks/assemble/data.ymlに定義したデータを表示できます。

{{baz.qux}}でmocks/assemble/baz.ymlに定義したデータを表示できます。

※data.yml以外のファイルに定義したデータは、ファイル名を接頭辞として付ける必要があるということです。

---
title: HOGE
---
<h1>HOGE</h1>
<p>{{foo}}</p>
<p>{{baz.qux}}</p>
{{> footer }}

include用テンプレート(hbs/includes/footer.hbs)

<footer>
</footer>

動作確認

とりあえず、assemble単体で実行し、ファイルのコンパイル処理を確認します。

$ grunt assemble

Running "assemble:hoge" (assemble) task
Assembling app/hoge.html OK
>> 1 pages assembled.

Running "assemble:moge" (assemble) task
Assembling app/moge.html OK
>> 1 pages assembled.

Done, without errors.

$ cat app/hoge.html

<!DOCTYPE HTML>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HOGE</title>
</head>
<body>
This is default layout.

<h1>HOGE</h1>
<p>bar</p>
<p>quux</p>
<footer>
</footer>


</body>
</html>

期待通りのHTMLが生成されています。

次にlivereloadも試してみましょう。

grunt serverでサーバを起動し、ブラウザからhttp://XXXX:10000/hoge.htmlにアクセスしておきます。

Running "server" task

Running "clean:server" (clean) task
Cleaning ".tmp"...OK

Running "concurrent:server" (concurrent) task
    
    Running "coffee:dist" (coffee) task
    File .tmp/scripts/hello.js created.
    
    Done, without errors.
        
    Running "compass:server" (compass) task
    
    Done, without errors.
    
Running "configureProxies" task
Proxy created for: /ajax to 0.0.0.0:8000

Running "connect:livereload" (connect) task
Starting connect web server on 0.0.0.0:10000.

Running "watch" task
Waiting...OK

watchタスクで監視対象に設定したファイル、例えばhbs/pages/hoge.hbsを適当に編集して保存してください。

すると、ブラウザで表示していた画面が自動でリロードされ、変更が反映されると思います。

grunt のログを見てみましょう。

>> File "hbs/pages/hoge.hbs" changed.

Running "assemble:hoge" (assemble) task
Assembling app/hoge.html OK
>> 1 pages assembled.

Done, without errors.
Completed in 2.412s at Tue Dec 24 2013 14:16:44 GMT+0000 (UTC) - Waiting...
OK
>> File "app/hoge.html" changed.

... Reload app/hoge.html ...
Completed in 0.000s at Tue Dec 24 2013 14:16:44 GMT+0000 (UTC) - Waiting...

下記の順に処理が実行されているのが分かります。

  1. watch:assembleHogeのタスクで設定したhbs/pages/hoge.hbsの更新を検知
  2. assemble:hogeのタスクが実行され、app/hoge.htmlが再生成される
  3. watch:livereloadのタスクで設定した<%= yeoman.app %>/*.htmlにより、app/hoge.htmlの更新が検知されlivereloadが実行される

assembleの動作について、手軽に試したい場合は下記のボイラープレートを試してみてください。

https://github.com/assemble/boilerplate-site