gruntやgulpでSSIを利用する

公開

Webサイトの設計・実装時に、Gruntgrunt-contrib-connectを利用してWebサーバーを立ち上げているのですが、ApacheのようにSSIが使えたらなと思うことが時々ありました。

今日「node.js ssi」でGoogle検索をしてみると、偶然1位にssi - npmを発見しました。さらに調べていくと、connect-ssiというMiddlewareを見つけました。テストしてみたところ、<!--#include file="foo/bar.txt" -->の記述で、bar.txtの内容がインクルードされました。これは使えそうです。

ただ、次の3点の問題があり修正してプルリクエストを送信しました(慣れていない上に英語が苦手なので申し訳ない感じですが...)。これらは取り込まれ、バージョン0.1.3として公開されました。

  • /foo/にアクセスした際に、/foo/index.htmlが表示されない
  • <!--#include virtual="/foo/bar.txt" -->が正しく動作しない
  • 複数のMiddlewareを使う場合、一番最後に指定しなければ正しく動作しない

(2015年1月20日追記)<!--#include file="/foo/bar.txt" -->のような記述でも、Apacheでvirtualを使う場合と同等の動作をしました。

grunt-contrib-connectプラグインの設定例

npm install --save-dev connect-ssiでインストールした後設定を行います。いつもCoffeeScriptで書くので、Js2Coffeeで変換した結果を掲載します。middlewareのところがポイントです。

'use strict';
var connectSSI = require('connect-ssi');

module.exports = function(grunt) {
  grunt.initConfig({
    connect: {
      livereload: {
        options: {
          hostname: '0.0.0.0',
          port: 3501,
          base: '../htdocs',
          livereload: true,
          middleware: function(connect, options) {
            return [
              connectSSI({
                baseDir: __dirname + '/htdocs',
                ext: '.html'
              }),
              connect["static"](options.base[0])
            ];
          },
          open: 'http://localhost:<%= connect.livereload.options.port %>/'
        }
      }
    }
  });
};

gulpの場合

gulp-webserverのmiddlewareオプションに「feature coming soon」とあるので、いずれ使えるようになるのでしょうか。試しにgulp file.coffeeを書いてみましたが、動作しませんでした。

BrowserSync + Gulp.jsであれば実現できます(下記参照)。

2015年1月20日追記

gulpの場合は次のような記述になります。

var gulp = require('gulp');

gulp.task('serve', function () {
    var connect = require('connect');
    var serveStatic = require('serve-static');
    var connectSSI = require('connect-ssi');
    var app = connect();

    app.use(connectSSI({
                baseDir: __dirname + '/htdocs',
                ext: '.html' // file extension. Only urls ending in this will be evaluated.
            }))
        .use(serveStatic(__dirname + '/htdocs'));
    app.listen(3501);
});

blackList入りのgulp-connectを使う場合は、次のようになります(middlewareが使えるようになっていました。)。

var gulp = require('gulp');

gulp.task('serve', function () {
    var connect = require('gulp-connect');
    var connectSSI = require('connect-ssi');

    connect.server({
        root: 'htdocs',
        port: 3501,
        middleware: function () {
            return [
                connectSSI({
                    baseDir: __dirname + "/htdocs",
                    ext: '.html' // file extension. Only urls ending in this will be evaluated.
                })
            ];
        }
    });
});

BrowserSyncの場合は?

connect-ssiの作者の方が、browsersync-ssiを公開されていますので、これを利用すればSSIが使えます。

ただし、connect-ssiに送信したプルリクエストの内容を反映してもらわないと、<!--#include virtual="/foo/bar.txt" -->が正しく動作しないようです。

2015年5月22日追記

試したところ、Githubのコードをインストールすると<!--#include virtual="/foo/bar.txt" -->も含めベストな状態で動作します。package.jsonのdevDependencies"browsersync-ssi": "soenkekluth/browsersync-ssi"と書いて、npm iしてみてください。generator-skywardでも正式採用しました。

gulpで利用する例(Gruntもほぼ同じです。)

var browserSync = require('browser-sync');
var ssi = require('browsersync-ssi');

gulp.task("browser-sync", function() {
  browserSync({
    server: {
      baseDir: "./htdocs",
      middleware: [
        ssi({
          baseDir: __dirname + "/htdocs",
          ext: ".html"
        })
      ]
    }
  });
});