ふんばりフロントエンジニアのブログ

新米フロントエンジニアの備忘録です。ふんばり温泉タオル欲しい...

AMP対応でインラインCSS書き出しをなんとか自動化した話 〜gulpfile編〜

明けましておめでとうございます!

なかなか年末まで案件が終わらずブログが更新できませんでした…泣

 

さて、そして年末まで取り組んでいた案件というのが今回のテーマであるAMP対応です。

AMPとは簡単にいってしまえば、Webページを高速化するための枠組みですね。

AMP独自のタグやコンポーネントを使うことで簡単にスライダーやカルーセルを実現できるので便利ではありますが、結構制約が多いんですよね…

 

たとえば、自分でJSを書くことができなかったりするのでちょっと動作を変えたいな〜とかいうときはCSSやAMPのコンポーネントをなんとか組み合わせてやらなきゃいけないわけです。

今回で言えば、カルーセルにスライダーのページネーションを組み込む、的なことをやろうと思ったのですがなかなかうまく行かず…
 

つまりコーディングする前に綿密に実現可能かどうかの調査が必要になります。
 

さて、色々な制約があるAMPなのですがこれらの制約の中でも「一番やだなー」って思ったものがインラインCSSです。

 

実はAMPではリクエストを減らすために、CSSの外部ファイル読み込みができないんですね。

そしてこのCSSはどこに書いていいわけでもなの中に記述しないといけないと…

 
まあチクチク書いていけばなんとかなりますが、プレフィクスもつけたいし最終的には圧縮したいわけですよ…

そしてCSSをいじっただけでリロードとかもしてもらいたいわけですよ…

gulpを使っている私ですが、せっかくいつも使っているタスクが利用できないのはかなりもどかしい…
 

ということで!

いつも通りの環境でコーディングできるように試行錯誤しながらインラインCSSを自動化した話をお届けしたいと思います。

 
今回インラインCSSの書き出しに使ったものでいつもと異なるのはPHP

別に言語はなんでもいいと思いますが、とりあえず勉強中という事もあってPHPを使うことにいたしました。


ではこのPHPがどのようにして役に立つのか、流れをご紹介していきたいと思います。


まず、ざっくりした図から見ていきましょう!

f:id:ma1129nm:20190120234338p:plain


このように、元となる「index_template.html」ファイルにコンパイルされたCSSを取り込んで、最終的にHTMLファイルとして吐き出すというのが大まかな流れ。

SCSSのコンパイルに関してはいくらでも参考になる記事があると思いますのでここでは割愛します。


では、肝心のtemplateからHTMLファイルを生成するまでにどのようなファイルが必要になるのか、主役は二つのファイルです。

  • gulpfile.js

...ご存知の通り、gulpを実行するためのファイル。

...templateとHTMLファイルの中身を入れ替えるためのファイル。


では、gulpfile.jsから内容を見ていきましょう。

const gulp = require('gulp');
const autoprefixer = require('gulp-autoprefixer');
const plumber = require('gulp-plumber');
const sass = require('gulp-sass');
const sourcemaps = require('gulp-sourcemaps');
const sync = require('browser-sync').create();
const ps = require('child_process').exec; //コマンドを打てるプラグイン 重要!!
let changeFileName;
const srcDir = './src';
const distDir = './';

gulp.task('replace', function () {
    var command = `php replace.php ${changeFileName}`;
    ps(command);
});

gulp.task('serve', () => {
    sync.init({
        server: './',
        port: 3333,
        notify: false
    });
    gulp.watch(['./templates/**/*.html',`${srcDir}/css/style.css`], (event) => {
        changeFileName = event.path.split('/').pop();
    });
    gulp.watch([`${srcDir}/**/*.scss`], ['sass', sync.reload]);
    gulp.watch(['./templates/**/*.html',`${distDir}/css/style.css`], ['replace',sync.reload]);
});

gulp.task('sass', () => {
    return gulp.src(`${srcDir}/css/style.scss`)
        .pipe(plumber())
        .pipe(sass({
            outputStyle: 'compressed'
        }).on('error', sass.logError))
        .pipe(sourcemaps.init())
        .pipe(autoprefixer({
            browsers: ['last 2 versions', 'ie >= 11', 'iOS >= 10', 'Android >= 4.4'],
        }))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest(`${distDir}/css/`));
});

さて、このgulpfile.jsで見慣れないタスクはreplaceというタスクでしょう。

このタスクはが行なっている処理はいたって単純でPHPコマンドを動かすだけ。

ただ、「${changeFileName}」というコマンドライン引数を渡していることに注目して下さい。

この${changeFileName}という引数はserveタスクを見てもらえるとわかるように、watchで監視しているHTMLファイルかSCSSファイルに変更があった場合に、そのファイル名を代入するための変数です。

言い忘れてましたが、ファイルの階層構造はこのような感じです。

f:id:ma1129nm:20190121000820p:plain

変更のあったファイルを取るのは「event.path」なのでこのプロジェクトのルートからパスが取れてしまうわけです。

そのため、index_template.htmlに変更があった場合「templates/index_template.html」というパス名が取得できるんですね。

それをsplitで分割して完全にファイル名だけを取れるようにしている、というのが一番上のwatchの中で行なっている処理となっています。

で、この取得したパス名を変数に入れてそのままコマンドライン引数として渡しているのですが、次に気になるのは引数が渡されているreplace.phpですよね。

このまま書き続けてもいいのですが、なんとなく長くなりそうなのでPHPファイルに関してはまた次にお話ししようと思います。