フロントエンドだけじゃない! サーバサイドの開発も手助けしてくれる grunt-connect-proxy を紹介するよ

<a href="http://www.gdefon.com/animals/428716-dog_home_guardian.html">![002.jpg](https://qiita-image-store.s3.amazonaws.com/0/27401/702f36e2-b506-49e2-b71a-1142d5b7ffcd.jpeg)</a>

© 2011 www.GdeFon.com
via. http://www.gdefon.com/animals/428716-dog_home_guardian.html

# grunt-connect-proxy
---

- [grunt-connect-proxy](https://github.com/drewzboto/grunt-connect-proxy)

grunt でプロキシサーバをたてることが出来るプラグインです。

``npm i -D grunt-connect-proxy``

## 特徴

もう単純にリバースプロキシするだけです。はい。

でもそれだけだと利点が分かりませんです。はい。

なので以下利点を2つ。

1. クロスドメイン問題の回避

    開発サーバで 複数ポート / 複数FQDN を 同一ドメイン下で リクエストハンドリング出来るようになります。

    例えば 本番環境ではAPI実装とアプリ実装が同一なのに、easymock などの APIモックサーバと開発サーバが別立ての場合、クロスドメイン制約があったりして色々と面倒です。

    それらを grunt-connect-proxyで解決する例を紹介します。

2. LiveReloadスクリプトの自動挿入とサーバサイド開発 

    grunt と聞くとフロントエンドのみで使うのでは? と思われるかもしれませんが、そんなことはありません。
    
    サーバサイドの開発でもgruntは重宝するんですよね。
 
    grunt といえば (自分の中では) LiveReload のイメージがあるので サーバサイドの開発で  LiveReload する例を紹介します。  


### クロスドメイン問題の回避

モックサーバ ( URLは localhost:3000/api とする ) に対し、フロントサーバ (localhost:9000 )でリバースプロキシを仕込みます

#### 設定例 (Gruntfile.js)

```js
var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest;

///...
connect: {
  static: {
    options: {
      port: 9000,
        hostname: 'localhost',
        middleware: function (connect) {
        return [
          connect.static(require('path').resolve("public_html")),
          proxySnippet
        ];
      }
    }
  },
  proxies: [{
    context: '/api',
    host: 'localhost',
    port: '3000',
    https: false,
    changeOrigin: false
  }]
}

grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-connect-proxy'); 

```


```js
  grunt.task.run([
    'configureProxies',
    'connect:static'
  ]);
```
 
以上の設定により、localhost:9000/api 以下へのアクセスは localhost:3000/api 以下を返すようになります。
(※  要 easymock サーバ起動、grunt による同時起動について今回は省略)


### LiveReloadスクリプトの自動挿入とサーバサイド開発

フローとしてはこうです。

一旦、フロントサーバ (例として8000番ポート) を grunt で立ち上げます。

リクエスト ``localhost:8000/`` 以下、つまりすべてのリクエストを任意のアプリケーションサーバ (例として phpサーバ 3333番ポート) へ流すリバースプロキシ設定を行ないます。

 PHPサーバから出力されるコンテンツと合わせて、grunt で立ち上げたフロントサーバがLiveReload用のスクリプトを挿入することで、結果として 拡張や開発者自身によるスクリプトを記述すること無く LiveReload が行えます。

#### LiveReloadの仕組み
そもそもの話としてLiveReloadの仕組みってどうなっているのでしょうか?

[tiny-lr](https://github.com/mklabs/tiny-lr) という websocket を 利用した  LiveReload 用 (デフォルト35729ポート) のスタンドアロンサーバを起動し、任意のタイミングでリクエストを送ることにより、script を読み込んでいるサーバに対しReload処理の命令を送るものです。

``grunt-contrib-watch`` 等はこの tiny-lr サーバを内部起動し、watch タスクで指定されたファイルの変更を監視してLiveReload 用サーバへリクエストを行なっています。

静的サイトの作成など、grunt 自身が立ち上げたサーバであれば、connect-livereload モジュールのスニペットを合わせて利用することで下記のスクリプトを出力時に挿入し、LiveReload が動く状態でブラウザを開くことが出来ます。

```html
<script type="text/javascript">document.write('<script src="' + (location.protocol || 'http:') + '//' + (location.hostname || 'localhost') + ':35729/livereload.js?snipver=1" type="text/javascript"><\/script>')</script>
``` 

しかし、grunt (Node.js) が立ち上げたサーバなら自身の出力にスクリプトを挿入することが出来るのですが、例えば PHP などのサーバに対してこのスクリプトを挿入することは叶いません。

なので、LiveReload用の[ブラウザ拡張](http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-) を使ったりするのですが、それすら面倒だという場合に ``grunt-connect-proxy`` を使います。
(コードにスクリプトを仕込んでおく。拡張使え。というツッコミはナシで)

#### 設定例 (Gruntfile.js) 

```js
  var LIVERELOAD_PORT = 35729;
  var lrSnippet = require("connect-livereload")({
    port: LIVERELOAD_PORT
  });
  var proxySnippet = require("grunt-connect-proxy/lib/utils").proxyRequest;

///...
  connect: {
    front: {
      options: {
        port: 8000,
          hostname: 'localhost',
          middleware: function (connect) {
          return [
            lrSnippet,
            connect.static(require('path').resolve("."),
              proxySnippet
          ];
        }
      }
    },
    proxies: [{
      context: '/',
      host: 'localhost',
      port: '3333',
      https: false,
      changeOrigin: false
    }],
    watch: {
      options: {
        livereload: true
      },
      php: {
        //CakePhp等の場合
        files: ["app/View/**/*.php", "app/Config/*.php"]
      },
      ctp: {
        //CakePhp等の場合
        files: "**/*.ctp"
      }
    }
  }

  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-connect-proxy');

```


```js
  grunt.task.run([
    "configureProxies",
    "connect:front",
    "watch"
  ]);
``` 

PHPなどの インタプリタ型 言語であれば .php ファイルの変更があった際、サーバを再起動をする必要は無いですね。

再起動が必要な言語の場合、どのようにサーバのリロードタイミングを合わせてブラウザリロード処理をするのが良いのでしょうか?

それらについては Grunt Plugins Advent Calendar 2013 20日目の投稿にて紹介します。

それでは。


### 利用した npm module

- grunt-connect-proxy
- grunt-contrib-connect
- connect-livereload 

## 参考

- [PhpStormからCakePHPをGrunt.jsで起動する](http://nantokaworks.com/p1222/)
- [Yeomanでフロントエンドとバックエンドサーバを一緒に開発する](http://nantokaworks.com/p1047/)

----
[Grunt Plugins Advent Calendar 2013 - Qiita [キータ]](http://qiita.com/advent-calendar/2013/grunt-plugins)