Upgrade to Pro — share decks privately, control downloads, hide ads and more …

モバイルページを爆速に ~Laravelで実現するAMP対応の自動化~ #PHPcon2017

yaizuuuu
October 08, 2017

モバイルページを爆速に ~Laravelで実現するAMP対応の自動化~ #PHPcon2017

PHPcon2017で発表を行ったスライドです。
#PHPcon2017
#PHPカンファレンス2017

yaizuuuu

October 08, 2017
Tweet

Other Decks in Programming

Transcript

  1. 自己紹介 名前: 小柳津 裕真(オヤイヅ ユウマ) 所属: 株式会社イノベーション 好きな技術: PHP, Laravel,

    AMP 普段はITトレンドというサービスを開発しています AWS re:Invent 2017参加予定
  2. アジェンダ 1. AMPってなに?? a. AMPとは何か b. なぜ早いのか c. どんな対応が必要なのか 2.

    自動化の方法 a. LaravelのMiddlewareを活用 b. 画像サイズを動的に取得
  3. アジェンダ 1. AMPってなに?? a. AMPとは何か b. なぜ早いのか c. どんな対応が必要なのか 2.

    自動化の方法 a. LaravelのMiddlewareを活用 b. 画像サイズを動的に取得
  4. <!doctype html> <html amp> <head> <meta charset="utf-8"> <link rel="canonical" href="hello-world.html">

    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1"> <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> <script async src="https://cdn.ampproject.org/v0.js"></script> </head> <body>Hello World!</body> </html>
  5. どんな対応が必要なのか CSSを一つのインライン要素にする https://www.ampproject.org/ja/docs/tutorials/create/presentation_layout <style amp-custom> body { background-color: white;} amp-img

    { background-color: gray; border: 1px solid black;} </style> 各 AMP ページで使える埋め込みスタイルシートは 1 つだけで、使用で きないセレクターもいくつかあります。
  6. アジェンダ 1. AMPってなに?? a. AMPとは何か b. なぜ早いのか c. どんな対応が必要なのか 2.

    自動化の方法 a. LaravelのMiddlewareを活用 b. 画像サイズを動的に取得
  7. LaravelのMiddlewareを活用 <?php namespace App\Http\Middleware; use Closure; class Middleware { public

    function handle($request, Closure $next) { $response = $next($request); return $response; } }
  8. LaravelのMiddlewareを活用 <?php namespace App\Http\Middleware; use Closure; class Middleware { public

    function handle($request, Closure $next) { $response = $next($request); return $response; } } // この記述でレスポンスの内容が取得できる
  9. LaravelのMiddlewareを活用 public function handle($request, Closure $next) { $response = $next($request);

    $content = $response->getContent(); return $response; } // この記述でレスポンスの // コンテンツ(HTML)を取得できる
  10. LaravelのMiddlewareを活用 public function handle($request, Closure $next) { $response = $next($request);

    $html = '<!DOCTYPE> <html> <head> <title>PHPcon2017</title> </head> <body><h1>PHPcon2017</h1></body> </html>'; $response->setContent($html); return $response; } // この記述でレスポンスの内容を変更できる
  11. LaravelのMiddlewareを活用 $response = $next($request); $content = $response->getContent(); $pattern = '/<img

    (\s|\w|[\^!"#$%&@\'()*+,.\/~;?:=\\-]|[^\x01-\x7E])+>/'; $replacement = '$0</amp-img>'; $content = preg_replace($pattern, $replacement, $content); $pattern = '/<img/'; $replacement = '<amp-img'; $content = preg_replace($pattern, $replacement, $content); $response->setContent($content); return $response;
  12. LaravelのMiddlewareを活用 $response = $next($request); $content = $response->getContent(); $pattern = '/<img

    (\s|\w|[\^!"#$%&@\'()*+,.\/~;?:=\\-]|[^\x01-\x7E])+>/'; $replacement = '$0</amp-img>'; $content = preg_replace($pattern, $replacement, $content); $pattern = '/<img/'; $replacement = '<amp-img'; $content = preg_replace($pattern, $replacement, $content); $response->setContent($content); return $response; //レスポンス内容のHTMLを取得
  13. LaravelのMiddlewareを活用 $response = $next($request); $content = $response->getContent(); $pattern = '/<img

    (\s|\w|[\^!"#$%&@\'()*+,.\/~;?:=\\-]|[^\x01-\x7E])+>/'; $replacement = '$0</amp-img>'; $content = preg_replace($pattern, $replacement, $content); $pattern = '/<img/'; $replacement = '<amp-img'; $content = preg_replace($pattern, $replacement, $content); $response->setContent($content); return $response; <img src=”~”> => <img src”~”></amp-img>
  14. LaravelのMiddlewareを活用 $response = $next($request); $content = $response->getContent(); $pattern = '/<img

    (\s|\w|[\^!"#$%&@\'()*+,.\/~;?:=\\-]|[^\x01-\x7E])+>/'; $replacement = '$0</amp-img>'; $content = preg_replace($pattern, $replacement, $content); $pattern = '/<img/'; $replacement = '<amp-img'; $content = preg_replace($pattern, $replacement, $content); $response->setContent($content); return $response; <img src”~”></amp-img> => <amp-img src”~”></amp-img>
  15. LaravelのMiddlewareを活用 $response = $next($request); $content = $response->getContent(); $pattern = '/<img

    (\s|\w|[\^!"#$%&@\'()*+,.\/~;?:=\\-]|[^\x01-\x7E])+>/'; $replacement = '$0</amp-img>'; $content = preg_replace($pattern, $replacement, $content); $pattern = '/<img/'; $replacement = '<amp-img'; $content = preg_replace($pattern, $replacement, $content); $response->setContent($content); return $response; //変更したHTMLをレスポンスの内容としてセット
  16. LaravelのMiddlewareを活用 //CSSのAMP対応 //AMPではCSSの!importantが使用できないので削除する $pattern = '/!important/'; $replacement = ''; $content

    = preg_replace($pattern, $replacement, $content); //AMPではタグ内のstyle属性が使用できないので削除する $pattern = '/style="*(\s|\w|[\^!#$%&@\'()*+,.\/~;?:=\\-])*"/'; $replacement = ''; $content = preg_replace($pattern, $replacement, $content);
  17. LaravelのMiddlewareを活用 $dom = new \DOMDocument(); @$dom->loadHTML($response->getContent()); $img_tag_list = $dom->getElementsByTagName("img"); foreach

    ($img_tag_list as $img_tag) { } //imgタグにheight・width属性をセットする処理を記述する
  18. LaravelのMiddlewareを活用 if ($img_tag->getAttribute('height') == "" && $img_tag->getAttribute('width') == "") {

    $filepath = $img_tag->getAttribute('src'); if (strpos($filepath, '//') === 0) { //CDNの場合 $filepath = 'https:' . $filepath; } elseif (strpos($filepath, '/') === 0) { //ローカルの場合 $filepath = ltrim($filepath, '/'); } @list($width, $height) = getimagesize($filepath); if ($width != "" && $height != "") { $img_tag->setAttribute('width', $width); $img_tag->setAttribute('height', $height); $img_tag->setAttribute('layout', 'responsive'); } } //高さ・幅が指定されていない場合は、 //画像サイズを取得して設定する ※foreach文の処理
  19. LaravelのMiddlewareを活用 if ($img_tag->getAttribute('height') == "" && $img_tag->getAttribute('width') == "") {

    $filepath = $img_tag->getAttribute('src'); if (strpos($filepath, '//') === 0) { //CDNの場合 $filepath = 'https:' . $filepath; } elseif (strpos($filepath, '/') === 0) { //ローカルの場合 $filepath = ltrim($filepath, '/'); } @list($width, $height) = getimagesize($filepath); if ($width != "" && $height != "") { $img_tag->setAttribute('width', $width); $img_tag->setAttribute('height', $height); $img_tag->setAttribute('layout', 'responsive'); } } //画像のパスを取得 ※foreach文の処理
  20. LaravelのMiddlewareを活用 if ($img_tag->getAttribute('height') == "" && $img_tag->getAttribute('width') == "") {

    $filepath = $img_tag->getAttribute('src'); if (strpos($filepath, '//') === 0) { //CDNの場合 $filepath = 'https:' . $filepath; } elseif (strpos($filepath, '/') === 0) { //ローカルの場合 $filepath = ltrim($filepath, '/'); } @list($width, $height) = getimagesize($filepath); if ($width != "" && $height != "") { $img_tag->setAttribute('width', $width); $img_tag->setAttribute('height', $height); $img_tag->setAttribute('layout', 'responsive'); } } //画像のサイズをセットする ※foreach文の処理