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

新米フロントエンジニアのふんばっている日々と備忘録です。

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

今回は前回の続き、ということでPHPファイルについてお話していこうと思います。

hubarifront.hatenablog.com


前回お話したgulpfileで重要だったのは、PHPコマンドを叩くタスクでしたね。

そしてこのタスクにはコマンドライン引数として変更したファイル名を渡していました。

では、その叩かれているPHPファイルがどのような処理を行なっているのか、見ていきましょう!


前回に引き続き、ファイルの階層構造はこちらです。

f:id:ma1129nm:20190121000820p:plain

で、まずはじめに見ていただきたいのがテンプレートとなるindex_template.htmlファイルです。

<!doctype html>
<html amp lang="ja">
<head>
  <meta charset="utf-8">
  <title>サンプルテキスト</title>
 
  <script type="application/ld+json">
[
  {
    "@context": "http://schema.org",
    "@type": "BreadcrumbList",
    "itemListElement": [
      {
        "@type": "ListItem",
        "position": 1,
        "item": {
          "@id": "https://sample.jp/",
          "name": "テキスト"
        }
      }
    ]
  }
]
</script>
  <style amp-custom>
    /*inline css*/
  </style>
  <style amp-boilerplate>body {
    -webkit-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
    -moz-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
    -ms-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
    animation: -amp-start 8s steps(1, end) 0s 1 normal both
  }

  @-webkit-keyframes -amp-start {
    from {
      visibility: hidden
    }
    to {
      visibility: visible
    }
  }

  @-moz-keyframes -amp-start {
    from {
      visibility: hidden
    }
    to {
      visibility: visible
    }
  }

  @-ms-keyframes -amp-start {
    from {
      visibility: hidden
    }
    to {
      visibility: visible
    }
  }

  @-o-keyframes -amp-start {
    from {
      visibility: hidden
    }
    to {
      visibility: visible
    }
  }

  @keyframes -amp-start {
    from {
      visibility: hidden
    }
    to {
      visibility: visible
    }
  }</style>
  <noscript>
    <style amp-boilerplate>body {
      -webkit-animation: none;
      -moz-animation: none;
      -ms-animation: none;
      animation: none
    }</style>
  </noscript>
</head>
<body>

</body>
</html>

はい、ご覧の通りかなり長ったらしいですがこれはほとんどAMPのデフォルトで記載しなければならないものばかり。

多分ここまではAMPのドキュメントを参照してもらえれば理解していただけると思います。

www.ampproject.org

さて、ここで肝心なのは次の部分。

<style amp-custom>
    /*inline css*/
  </style>

本来ならCSSを記載しなければならないstyleタグの中に「inline css」とコメントアウトが入っています。

これがトリガーになっていて、最終的にはこのコメントアウトコンパイルされたCSSに置換されるようになる、という想定です。

そしてHTMLファイルも編集するのはこのテンプレートファイルで、HTMLとCSSを混ぜ合わせた別のHTMLファイル、ここで言えばindex.htmlが出力されるということになります。


これは前回も貼りましたがイメージはこんな感じです。

f:id:ma1129nm:20190120234338p:plain


前置きが少し長くなってしまいましたが、ようやく本題のPHPファイルを見てみましょう。

<?php
//コマンドライン引数を取得 -> php replace.php _index_template.html
$cmdtemplate = $argv[1]; //_index_template.html
$cmdhtml = explode("_",$cmdtemplate)[1];//index

//templateディレクトリからファイル名を取得するための配列
$templatelist = array();

//第一引数に指定したファイルで第二引数に指定したファイルを置換
function replace($template,$html) {
    $css = file_get_contents("./css/style.css"); //scssからコンパイルされたCSS
    $replacing = file_get_contents("./templates/".$template);
    $replaced = str_replace("/*inline css*/",$css,$replacing);
    file_put_contents("./".$html.".html",$replaced);
}

foreach(glob('templates/*') as $file){
    if(is_file($file)){
        array_push($templatelist, htmlspecialchars($file));
    }
}

if( strpos($cmdtemplate,"html") !== true ){
    replace($cmdtemplate,$cmdhtml);
} else {
    foreach ($templatelist as $list){
        $t = explode("/",$list)[1];
        $h = explode("_",$t)[1];
        replace($t,$h);
    }
}

では、ポイントごとにコードの解説をしていきたいと思います。

まずは変数の宣言からいきましょう。

<?php
//コマンドライン引数を取得 -> php replace.php _index_template.html
$cmdtemplate = $argv[1]; //_index_template.html
$cmdhtml = explode("_",$cmdtemplate)[1];//index

//templateディレクトリからファイル名を取得するための配列
$templatelist = array();

ここでは、コマンドライン引数の取得をし、.htmlを除いた名前を取得しています。

コマンドライン引数は「$argv」で取れるらしいですね。

で、次に宣言している配列はindex_template.htmlなどのテンプレートファイルが入っているtemplatesディレクトリからファイル名を取得するための変数です。

合計AMPページが3ページほどあったのでこのような配列を宣言していますが1ページだけなら不要です。

では次はメインの関数であるreplaceを見てみましょう。

//第一引数に指定したファイルで第二引数に指定したファイルを置換
function replace($template,$html) {
    $css = file_get_contents("./css/style.css"); //SCSSからコンパイルされたCSS
    $replacing = file_get_contents("./templates/".$template);
    $replaced = str_replace("/*inline css*/",$css,$replacing);
    file_put_contents("./".$html.".html",$replaced);
}


このreplace関数は二つの引数があり、コメントアウトにも書いていますが、第一引数のファイルで第二引数に指定したファイルを置換するという関数です。

まず、コンパイルされたCSSを「file_get_contens」で取得し、変数に入れます。

そして対象となるテンプレートファイル(index_template.html)を取得し、$repacingに入れていますね。

で、その$replacingの中で「/*inline css*/」とコメントアウトされている部分を先ほどの$cssで置換し、$replacedに入れます。

この時点でindex_template.htmlにはCSSが入っていますが、このままだと「/*inline css*/」が消えてしまうので「file_put_contents」をするのは出力先であるindex.htmlにするわけです。

あとはこのreplace関数をどのように実行させるかの条件ですね。


if( strpos($cmdtemplate,"scss") !== true ){
    replace($cmdtemplate,$cmdhtml);
} else {
    foreach ($templatelist as $list){
        $t = explode("/",$list)[1];
        $h = explode("_",$t)[1];
        replace($t,$h);
    }
}

とりあえず、複数ページの想定なので共通のSCSSなどがあるわけです。

もちろんそのSCSSを編集した場合は全部のHTMLファイルに更新をかけたいのでtemplateファイルを格納している$templatewをforeachで回してreplace関数を全テンプレートファイルにかけています。

しかし、HTMLだけを編集した場合に全部のHTMLファイルに更新をかける必要はありませんよね。

そのため、コマンドライン引数、つまり変更したファイルにscssという文字がなければコマンドライン引数のファイルのみを置換する、という分岐をしています。

これでなんとか置換することができました。

実際にはこのような形に…

f:id:ma1129nm:20190127124731p:plain

ここまで来るのに結構時間がかかってしまいましたが、PHPのお勉強としてはかなり有意義だったような気がします。

またgulpでコマンドを打ったり、イベントを取得するということも始めてだったので今後色々使っていきたいですね!


ちょっとまとまりがない記事になってしまったかもしれませんが、逐一確認して修正していきます(汗