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

フロントエンド、私的リリース戦略史 / Connehito Marche Online Front-End release strategy

フロントエンド、私的リリース戦略史 / Connehito Marche Online Front-End release strategy

mediba社合同勉強会】コネヒトマルシェオンライン「祝書籍出版!両社のフロントエンド事情大公開」

発表資料
https://connehito.connpass.com/event/193896/

Satoshi Takeda

November 12, 2020
Tweet

More Decks by Satoshi Takeda

Other Decks in Programming

Transcript

  1. フロントエンド 私的リリース戦略史 【mediba 社合同勉強会】 コネヒトマルシェオンライン @tkdn

  2. whoami { { "name" "name" : : " 武⽥ 諭

    " " 武⽥ 諭 ", , "from" "from" : : " 株式会社 mediba" " 株式会社 mediba", , "job" "job" : : " フロントエンド開発者 " " フロントエンド開発者 ", , "social" "social": : "tkdn" "tkdn", , "career" "career": : { { "2003-2013" "2003-2013" : : " 役者 " " 役者 ", , "2013-" "2013-" : : " エンジニア " " エンジニア " } } } }
  3. None
  4. [PR] 書籍紹介 担当したのは Part 1 導⼊編, Part 3 応⽤編

  5. [PR] 書籍紹介 特定技術よりも解決する課題を扱う フロントエンドを取り囲むエコシステムを浅く広く扱ってます 例えば SSG (静的サイト⽣成) ※ SSG は書籍で扱ってません

    DreamWeaver ⇢ Middleman ⇢ Next.js 解決している根本課題は同じ (周回毎に解決していることは微妙に違う
  6. [PR] 書籍紹介 特定技術よりも解決する課題を扱う 例)SSG 変遷 共通する解決したい課題は ✅ 画⾯を⼤量⽣成したい

  7. [PR] 書籍紹介 SSG 変遷: DreamWeaver Web 制作におけるページ量産を効率化 Adobe デザイン・マークアップフルセット ✅

    ⼿動で作るより テンプレートに合わせて 画⾯を⼤量⽣成したい
  8. SSG 変遷: Middleman, Jekyll, Hugo 世は SSG 戦国時代(だった(⾔語も多種多様 ✅ ⼿動で作るより

    プログラマブルに 画⾯を⼤量⽣成したい
  9. SSG 変遷: Next.js, Gatsby, Nuxt 世は JavaScript ⼀強時代(バイアス ✅ フレームワーク(巨⼈)の肩の上で

    画⾯を⼤量⽣成したい フロントエンドに特化しているので パフォーマンス、開発体験
  10. 本題

  11. 今⽇話すこと「リリースの話」 「フロントエンドのリリースどうしてますか」 「どういった戦略でデプロイにのぞみますか」

  12. アジェンダ 1. 私的リリース史 2. リリース史観から戦略へ応⽤する 3. まとめ

  13. 1. 私的リリース史

  14. 私的リリース史 A. 静的ファイルがまとまっているパターン B. バックエンド FW が中⼼のパターン C. フロントエンド特化のパターン

  15. 私的リリース史 A 静的ファイルがまとまっているパターン 200x-201x 年初頭あたりの Web 制作・開発 Node.js を中⼼とした、ツールチェーン掛け合わせの爆発的増加 成果物は

    SFTP, SCP でアップロード 選択肢とデプロイが⾃由すぎる マニュアル操作で不穏な匂いがする
  16. 私的リリース史 B バックエンド FW が中⼼のパターン 201x 年中頃の Web 開発 FuelPHP

    、Laravel 、Rails 、Yii などの バックエンドFW フロントエンドは控えめに載っかっている バックエンドFW のテンプレートエンジン
  17. 私的リリース史 B バックエンド FW が中⼼のデプロイ fabric, capistrano, deployer... フロントエンドのソースは別でデプロイ フロントエンドが通常デプロイフローと区別される

    画⾯に必要なアセットファイルの存在有無が未確定
  18. 私的リリース史 B mediba ジョイン時のあるデプロイ

  19. 私的リリース史 C フロントエンド特化のパターン 最近関わっている mediba のプロジェクト Next.js SSR/SSG 、React SPA

    ✅ フロントエンドに軸を置いているので フロントエンド中⼼のメリットを享受できる
  20. メリット1: Optimized Cache Busting 中間キャッシュをパージする画⾯サブリソースの参照 URL 変更 < <link link

    rel rel= =" "stylesheet stylesheet" " href href= =" "https://awsesome-app.com/css/style.css?cache=1604818365 https://awsesome-app.com/css/style.css?cache=1604818365" "> > < <script script src src= =" "https://awsesome-app.com/js/app.js?cache=1604818365 https://awsesome-app.com/js/app.js?cache=1604818365" "> ></ </script script> >
  21. メリット1: Optimized Cache Busting 本当に⼤丈夫? 雰囲気でパラメータつけてない? e.g. Cloudfront query string

    forwarding
  22. メリット1: Optimized Cache Busting 昨今のフロントエンド事情 webpack でのコンパイルでフォローが可能 // webpack config...

    // webpack config... output output: : { { // ⽣成されるファイルのダイジェスト値により変わる // ⽣成されるファイルのダイジェスト値により変わる filename filename: : '[name].[contenthash].js' '[name].[contenthash].js', , path path: : path path. .resolve resolve( (__dirname __dirname, , 'dist' 'dist') ), , } }, , < <link link rel rel= =" "stylesheet stylesheet" " href href= =" "https://awsesome-app.com/css/style.0cf28fbf.css https://awsesome-app.com/css/style.0cf28fbf.css" "> > < <script script src src= =" "https://awsesome-app.com/js/app.7847e54d.js https://awsesome-app.com/js/app.7847e54d.js" "> ></ </script script> >
  23. メリット2: Long Term Caching 変更のないファイルはクライアントに中間キャッシュを提供 ムダな通信を発⽣させずキャッシュを最⼤限有効活⽤

  24. メリット2: Long Term Caching 例) Next.js リリース 1 回⽬

  25. メリット2: Long Term Caching 例) Next.js リリース 2 回⽬

  26. メリット3: Valid Cache メリット1:最適化されたキャッシュバスト メリット2:⻑期的キャッシュ戦略 ゆえにアプリバージョン毎にユニーク つまり? リリース前後で参照するサブリソースが全く違うので ローリングアップデート中に不幸がない

  27. メリット3: Valid Cache

  28. メリット3: Valid Cache

  29. メリット3: Valid Cache なんでそんなに気にするの? ユーザーに届いてからの体験は正直何が起こるか分からない 実体験) 半年前リリースした資材になぜかまだリクエストがある… リプレイスしているのに前の API にリクエストがある(なんで…

  30. C パターンのリリース戦略とはつまり… ユーザーのためのキャッシュ戦略

  31. 2. リリース史観から戦略へ応⽤する

  32. 2. リリース史観から戦略へ応⽤する 必ずしも C パターンだけではない 必ずしもフロントエンド特化ではない B だって全然ありえるパターン バックエンド FW

    中⼼ということも全然ありえる
  33. 再掲) mediba ジョイン時のあるデプロイ まずこの課題をクリアしたい

  34. 1.webpack のビルド時に manifest.json を作成 { { "/assets/css/app.css" "/assets/css/app.css": : "/assets/css/app.640bde4c.css"

    "/assets/css/app.640bde4c.css", , "/assets/css/page-a.css" "/assets/css/page-a.css": : "/assets/css/page-a.201ed25f.css" "/assets/css/page-a.201ed25f.css", , "/assets/css/page-b.css" "/assets/css/page-b.css": : "/assets/css/page-b.b1b57f9f.css" "/assets/css/page-b.b1b57f9f.css", , "/assets/js/app.js" "/assets/js/app.js": : "/assets/js/app.39540668.js" "/assets/js/app.39540668.js", , "/assets/js/page-a.js" "/assets/js/page-a.js": : "/assets/js/page-a.9bf31e12.js" "/assets/js/page-a.9bf31e12.js", , "/assets/js/page-b.js" "/assets/js/page-b.js": : "/assets/js/page-b.7b3b2b62.js" "/assets/js/page-b.7b3b2b62.js" } }
  35. 2. バックエンドで json を読み出す まあいろいろやって読む。

  36. 3. json からパス⽣成するビューヘルパー実装 json ファイルキーから実パスを作成 パスを参照した script タグを作る例(PHP /** /**

    * @param string $url * @param string $url * @param array $attrs * @param array $attrs * @return HtmlString * @return HtmlString */ */ public public static static function function script script( (string $url string $url, , array $attrs array $attrs = = [ [] ]) ): : HtmlString HtmlString { { $filepath $filepath = = self self: :: :asset asset( ($url $url) ); ; $attributes $attributes = = self self: :: :attributes attributes( ($attrs $attrs) ); ; return return new new HtmlString HtmlString( ('<script src="' '<script src="' . . $filepath $filepath . . '" ' '" ' . . $attributes $attributes . . '></script>' '></script>') ); ; } }
  37. 4. テンプレートディレクティブ // ... なんやかんや // ... なんやかんや @script("/assets/js/app.js") @script("/assets/js/app.js")

    <!-- output: --> <!-- output: -->< <script script src src= =" "/assets/js/app.39540668.js /assets/js/app.39540668.js" "> ></ </script script> > </ </body body> > </ </html html> >
  38. こんなことをしなくても 昨今のバックエンドフレームワークは 準備が整っている

  39. 例) Laravel 5.8 laravel new app ルートに webpack.mix.js がいる webpack

    の⼩難しいところを 隠蔽したラッパーパッケージ
  40. 最適化を戦略へ応⽤ 1.webpack.mix.js const const mix mix = = require require(

    ('laravel-mix' 'laravel-mix') ); ; mix mix. .js js( ('resources/js/app.js' 'resources/js/app.js', , 'public/js' 'public/js') ) . .sass sass( ('resources/sass/app.scss' 'resources/sass/app.scss', , 'public/css' 'public/css') ) . .version version( () ); ; // この⾏だけスキャッフォルド時点では⼊っていない // この⾏だけスキャッフォルド時点では⼊っていない
  41. 最適化を戦略へ応⽤ 2. マニフェスト作成 ビルドコマンドはすでに⽤意されている { { "/js/app.js" "/js/app.js": : "/js/app.js?id=2f472fa1cb8208a4b3f4"

    "/js/app.js?id=2f472fa1cb8208a4b3f4", , "/css/app.css" "/css/app.css": : "/css/app.css?id=99bb964c34fbf0372f70" "/css/app.css?id=99bb964c34fbf0372f70" } }
  42. 最適化を戦略へ応⽤ 3. テンプレートから利⽤ mix は付属のヘルパー関数 < <link link rel rel=

    =" "stylesheet stylesheet" " href href= =" "{{ mix('css/app.css') }} {{ mix('css/app.css') }}" " /> /> < <script script src src= =" "{{ mix('js/app.js') }} {{ mix('js/app.js') }}" "> ></ </script script> >
  43. 例) Rails 6.0 rails new app webpacker がデフォルトで⼊っている webpack の⼩難しいところを

    隠蔽したラッパーパッケージ ※ … と思ったが使い勝⼿に癖があって少し⼾惑った
  44. 最適化を戦略へ応⽤ 1.app/javascript/packs/ にファイル設置

  45. 最適化を戦略へ応⽤ 2. マニフェスト⽣成 ビルドコマンドはすでに⽤意されている

  46. 最適化を戦略へ応⽤ 3. テンプレートへ記述 <%= stylesheet_pack_tag 'app' %> <%= stylesheet_pack_tag 'app'

    %> <%= stylesheet_pack_tag 'styles/another' %> <%= stylesheet_pack_tag 'styles/another' %> </ </head head> > < <body body> > <%= javascript_pack_tag 'app' %> <%= javascript_pack_tag 'app' %> <%= javascript_pack_tag 'scripts/another' %> <%= javascript_pack_tag 'scripts/another' %> </ </body body> >
  47. 実装サンプル tkdn/release-strategy-working

  48. 2. リリース史観から戦略へ応⽤する 適切なリリース戦略実現のために バックエンドフレームワークとの協調で何が必要そうか? 1. フロントエンドのあるべき姿を共有 2. フロントエンドビルドパイプラインをデプロイフローへ合流させる 3. リリース・キャッシュ戦略はチームで考える

  49. 3. まとめ

  50. 3. まとめ 昨今の JS フレームワークはフロントエンドに 最適化されたリリース・キャッシュ戦略が込み メリット1:Optimized Cache Busting メリット2:Long

    Term Caching メリット3:Valid Cache
  51. 3. まとめ 最適化されたフロントエンドの戦略を バックエンドフレームワークにも持ち込む場合 昨今のフレームワークは⽤意がある (なければ⾃作して) 開発チームの理解を得て リリースとフロントエンドビルドパイプラインを合流させよう

  52. 参考資料その 1 テンプレート機能を使ってみよう パート1 :「編集可能領域」と「オプ ション領域」の使い⽅ | デベロッパーセンター Static Site

    Generators - Top Open Source SSGs | Jamstack
  53. 参考資料その 2 Caching | webpack ブラウザのキャッシュを活⽤する | PageSpeed Insights |

    Google Developers Prevent unnecessary network requests with the HTTP Cache Caching best practices & max-age gotchas - JakeArchibald.com
  54. 参考資料その 3 クエリ⽂字列パラメータに基づくコンテンツのキャッシュ - Amazon CloudFront S3 バケットのライフサイクルポリシーを作成する⽅法 - Amazon

    Simple Storage Service medz/webpack-laravel-mix-manifest: A webpack plugin that generates Laravel framework compatible mix-manifest.josn le. JeffreyWay/laravel-mix: The power of webpack, distilled for the rest of us. rails/webpacker: Use Webpack to manage app-like JavaScript modules in Rails