grunt-connect-proxy, grunt-stubbyを利用してAjax用のJSON(モックデータ)を取得する[grunt]

yeomanのgenerator-mobile, generator-webappなどを利用すれば、静的なサイトを実装できる環境は簡単に用意できました。

但しその環境は、静的なファイル(html, css, jsなど)にアクセスして表示できるだけの環境でしかありません。

jsでUIを実装したくても、特定のURLにアクセスするとAjax用のJSON(モックデータ)を返すようなうまい仕組みがあるわけでもありません。

そこで、今回はgrunt-connect-proxy, grunt-stubbyを利用して、Ajax用のJSON(モックデータ)を取得する環境を構築したいと思います。

https://github.com/drewzboto/grunt-connect-proxy

https://github.com/h2non/grunt-stubby

https://github.com/mrak/stubby4node

install

$ npm i grunt-stubby -D

$ npm i grunt-connect-proxy -D

ポート番号の管理

grunt-stubby, grunt-connect-proxy, grunt-contrib-connect, connect-livereloadなど、ポート番号をパラメタに設定するタスクが多くなってくると、ポート番号の管理が煩雑になってきます。

ユーザ毎に設定を分けることも考慮すると、ポート番号の設定を別ファイルにした方が良いです。

$ vi port.json

{
  "connect": {
    "livereload": 10000,
    "dist": 20000
  },
  "livereload": 30000,
  "stubby": {
    "stubs": 8000,
    "tls": 8443,
    "admin": 8010
  }
}

grunt-stubbyのタスクを設定

stubbyの定義ファイルのディレクトリはmocks/stubby/としています。

$ vi grunt/stubby.js

'use strict';

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

module.exports = function(grunt) {

    grunt.config('stubby', {
        stubsServer: {
            // note the array collection instead of an object
            options: {
                callback: function (server, options) {
                    server.get(1, function (err, endpoint) {
                        if (!err) {
                            console.log(endpoint);
                        }
                    });
                },
                stubs: port.stubby.stubs,
                tls: port.stubby.tls,
                admin: port.stubby.admin,
                location: '0.0.0.0',
                persistent: true
            },
            files: [{
                src: [ 'mocks/stubby/**/*.yaml' ]
            }]
        }
    });

};

※callbackについては正常動作確認後削除して構いません。

grunt-stubbyのモックデータを設定

stubbyの定義ファイルを配置するディレクトリを作成します。

$ mkdir -p mocks/stubby

今回は例として「/ajax/hoge/」にGETメソッドでアクセスした場合に、任意のデータを返すように設定したいと思います。

リクエストのルーティングやレスポンスなどの定義ファイルを作成します。

今回はyamlを定義ファイルとして利用することとします。

リクエストのURI、メソッド、リクエストパラメタ(クエリストリング, postパラメタ)、ヘッダなどを指定してルーディングを設定できます。

レスポンスはHTTPステータスやヘッダ、ボディはもちろんのこと、レイテンシなども設定できます。

詳しくはhttps://github.com/mrak/stubby4nodeを参照してください。

$ vi mocks/stubby/hoge.yaml

-
  request:
    url: ^/ajax/hoge/$
    method: GET
  response:
    -
      status: 200
      headers:
        content-type: application/json
      file: mocks/stubby/hoge/get.json

上記でbodyの情報をfileで定義したので、bodyの定義ファイルを生成します。

$ mkdir -p mocks/stubby/hoge

$ vi mocks/stubby/hoge/get.json

{
    "foo":"1",
    "bar":"2"
}

grunt-connect-proxyのタスクを設定

  • connect.proxies設定
  • connect.livereload.middlewareにrequire('grunt-connect-proxy/lib/utils').proxyRequest追加
  • connect.dist.middlewareにrequire('grunt-connect-proxy/lib/utils').proxyRequest追加
  • 各種ポート番号の指定を、port.jsonの設定値に変更
  • serverタスクにconfigureProxies追加

$ vi Gruntfile.js

livereloadのポート番号

//var LIVERELOAD_PORT = 35729;
//var lrSnippet = require('connect-livereload')({port: LIVERELOAD_PORT});
var port = require('./port.json');
var lrSnippet = require('connect-livereload')({port: port.livereload});
        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']
            },
            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}'
                ]
            },
        },
        connect: {
            options: {
                // change this to '0.0.0.0' to access the server from outside
                hostname: '0.0.0.0'
            },
            livereload: {
                options: {
                    port: port.connect.livereload,
                    middleware: function (connect) {
                        return [
                            lrSnippet,
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, yeomanConfig.app),
                            require('grunt-connect-proxy/lib/utils').proxyRequest
                        ];
                    }
                }
            },
            test: {
                options: {
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, '.tmp'),
                            mountFolder(connect, 'test')
                        ];
                    }
                }
            },
            dist: {
                options: {
                    port: port.connect.dist,
                    middleware: function (connect) {
                        return [
                            mountFolder(connect, yeomanConfig.dist),
                            require('grunt-connect-proxy/lib/utils').proxyRequest
                        ];
                    }
                }
            },
            proxies: [
                {
                    context: '/ajax',
                    host: '0.0.0.0',
                    port: port.stubby.stubs,
                    https: false,
                    changeOrigin: false,
                    xforward: false
                }
            ]
        },
    grunt.registerTask('server', function (target) {
        if (target === 'dist') {
            //return grunt.task.run(['build', 'open', 'connect:dist:keepalive']);
            return grunt.task.run(['build', 'connect:dist:keepalive']);
        }

        grunt.task.run([
            'clean:server',
            'concurrent:server',
            'configureProxies',
            'connect:livereload',
            //'open:server',
            'watch'
        ]);
    });

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

    grunt.registerTask('build', [
        'clean:dist',
        'useminPrepare',
        'concurrent:dist',
        'configureProxies',
        'cssmin',
        'responsive_images:dev',
        'concat',
        'uglify',
        'copy',
        'rev',
        'usemin'
    ]);

動作検証

とりあえず、grunt-stubby単体で動作確認します。

$ grunt stubby

Running "stubby:stubsServer" (stubby) task
Stubby HTTP server listening on port 8000
Stubby HTTPS server listening on port 8443
Admin server listening on port 8010
{ request: { url: '^/ajax/hoge/$', method: 'GET', headers: {} },
  response: 
   [ { headers: [Object],
       status: 200,
       file: 'mocks/stubby/hoge/get.json',
       body: '' } ],
  id: 1 }

上記のようにcallbackで設定したログが表示されていれば起動できているはずです。

ブラウザからポート番号8000を指定してアクセスし、mocks/stubby/hoge/get.jsonの内容が取得できればOKです。

http://xxxx.com:8000/ajax/hoge/

続けて、grunt-connect-proxyの動作検証をします。

stubbyを起動した状態で通常の開発用のサーバを起動します。

$ grunt server

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

注目するのは下記2行です。

Proxy created for: /ajax to 0.0.0.0:8000
Starting connect web server on 0.0.0.0:10000

まずブラウザから10000ポートにアクセスして、通常の開発環境にアクセスできることを確認しましょう。

http://xxxx.com:10000

次に

http://xxxx.com:10000/ajax/hoge/

にアクセスしてみましょう。

ポート番号8000でアクセスした場合と同じ結果が得られれば成功です。