HTMLメール作成時のインラインスタイル化をgulpで行う


別の記事でも書きましたが、HTMLメールを作るときはスタイルをインラインで書かないといけません。
もちろん、直接インラインでスタイルを定義するのは大変なので、<style>タグに書かれたCSSをインライン化するWebサービス(ジェネレータ)なんかを使ってインラインスタイル化したりするわけですが、いちいちジェネレータにソースをコピペするのは面倒くさいです。
ソースが変更されたら、インラインでスタイルが書かれたHTMLファイルが自動生成されるのが望ましい。

というわけでGulpです。
以下のような一連のタスクを、ファイルが変更される度に実行します。
EJSはお試しで使ってみた感じ。

  1. EJSからHTMLを生成
  2. SassからCSSを生成
  3. 2で生成したCSSを1で生成したHTMLにインラインで挿入
  4. 完成したHTMLをminify

全然大したことしてないですね。
gulpfileや必要なパッケージは以下のとおりなので、HTMLメールを作る人は是非。

gulpfile.babel.js
import gulp from 'gulp';
import ejs from 'gulp-ejs';
import sass from 'gulp-sass';
import inlineCss from 'gulp-inline-css';
import htmlmin from 'gulp-htmlmin';
import plumber from 'gulp-plumber';
import notify from 'gulp-notify';
import runSequence from 'run-sequence';
import browserSync from 'browser-sync';

const dir = {
    path: '',
    src: 'src',
    dst: 'dst'
};

const options = {
    ejs: {},

    sass: {
        outputStyle: 'expanded'
    },

    inlineCss: {
        applyStyleTags: false,
        removeStyleTags: false
    },

    htmlmin: {
        removeComments: true,
        collapseWhitespace: true
    },

    serve: {
        open: true,
        notify: false,
        startPath: dir.path,
        server: {
            baseDir: './',
            index: `${dir.dst}${dir.path}/`,
            routes: {
                [dir.path]: `${dir.dst}${dir.path}/`
            }
        }
    }
};


gulp.task('ejs', () => {
    return gulp.src([`./${dir.src}/**/*.ejs`, `!./${dir.src}/**/_*.ejs`])
        .pipe(plumber({
            errorHandler: notify.onError('<%= error.message %>')
        }))
        .pipe(ejs(options.ejs))
        .pipe(gulp.dest(`./${dir.dst}/`));
});

gulp.task('sass', () => {
    return gulp.src(`./${dir.src}/styles/**/*.{scss,sass}`)
        .pipe(plumber({
            errorHandler: notify.onError('<%= error.message %>')
        }))
        .pipe(sass(options.sass))
        .pipe(gulp.dest(`./${dir.dst}/styles/`));
});

gulp.task('inlineCss', () => {
    return gulp.src(`./${dir.dst}/**/*.html`)
        .pipe(plumber({
            errorHandler: notify.onError('<%= error.message %>')
        }))
        .pipe(inlineCss(options.inlineCss))
        .pipe(gulp.dest(`./${dir.dst}/`));
});

gulp.task('htmlmin', () => {
    return gulp.src(`./${dir.dst}/**/*.html`)
        .pipe(htmlmin(options.htmlmin))
        .pipe(gulp.dest(`./${dir.dst}/`));
});

gulp.task('serve', () => {
    browserSync(options.serve);
});

gulp.task('build', cb => {
    runSequence(
        'ejs',
        'sass',
        'inlineCss',
        'htmlmin',
        cb
    );
});

gulp.task('default', ['build', 'serve'], () => {
    gulp.watch(`./${dir.src}/**/*.ejs`, ['build', browserSync.reload]);
    gulp.watch(`./${dir.src}/styles/**/*.{scss,sass}`, ['build', browserSync.reload]);
});
package.json
{
  "private": true,
  "engines": {
    "node": "0.12.x"
  },
  "scripts": {
    "start": "gulp"
  },
  "devDependencies": {
    "babel-core": "^5.8.23",
    "browser-sync": "^2.8.2",
    "gulp": "^3.9.0",
    "gulp-ejs": "^1.2.0",
    "gulp-htmlmin": "^1.1.4",
    "gulp-inline-css": "^2.0.0",
    "gulp-notify": "^2.2.0",
    "gulp-plumber": "^1.0.1",
    "gulp-sass": "^2.0.4",
    "run-sequence": "^1.1.2"
  }
}

Template stringsほんと便利。