こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/service_definition_parameters.html この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 https://aws.amazon.com/jp/blogs/news/amazon-ecs-service-discovery/ これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? https://www.medley.jp/jobs/engineer1.html
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
メドレーのデザイナー酒井です。最近、 JobMedley から CLINICS に異動しました。 自分はデザインはもちろん、HTML/CSS/JS 実装してプルリク送ったりしているちょっとフロントエンド実装領域に軸足が寄ったタイプのデザイナーです。 ここでは以前所属していた JobMedley 事業部の話をさせていただきます。 当時、JobMedley の社内システムのリニューアルプロジェクトにデザイナーとして参加していました。通常、デザイナーがデザインをするときには Skecth や Figma のようなデザインツールを利用するのが一般的かと思います。 弊社でも基本的にはデザインツールでデザインを行うことが多いのですが、プロジェクトによっては、よりリアルなモックアップが必要なため、デザイナー自身がコーディングでデザインを行い、ブラッシュアップしていくことがあります。その後、フロントエンド実装者が、デザイナーが作ったデザインを参考に、しっかりと設計されたもので作り直します。 今回のリニューアルプロジェクトのデザイン・モックアップの制作では、Figma や Sketch などのデザインツールは使用せず、React でコーディング行い、デザインを制作しています。ここが特殊な制作フローになると思うので、このエントリでは React をデザインツールとして使ったときの流れとメリット・デメリット、ちょっとニッチなポイントに絞ってお話していきます。 デザインの流れ 1.まずは React を勉強する 元々受託制作会社でデザイナーをやっていた時代に Vue.js での開発経験はありましたが、React は今回が初めてでした。そのため、一旦公式チュートリアルを一通り読み、Google などで調べつつ、基礎知識のインプットすることからはじめました。 2.ワイヤーフレームを作る さすがにワイヤーフレーム無しでコード実装には入れないので、ここでは Figma などのツールを使います。ワイヤーフレームを作り、要件定義を進めていきますが、デザインに関してもある程度のあたりを付けていきます。 3.開発環境構築 今回は Next.js で制作を行っています。 そもそも、プロダクトの実装で Next.js を使用することが決まっていたので、デザイン側も Next.js を採用しましたが、結果的に良かったなと感じています。 Next.js で作っておけば、めんどくさい router の設定やデザイナーが苦手な webpack の config を記述しなくてすみます。 また、 next build && next export で静的な HTML ファイルとして書き出されるため、サーバがあればすぐに共有が可能です。今回はエンジニアさんに、develop ブランチに merge されると、 next build && next export が走り、自動で Amazon S3 に静的ファイルをデプロイされるようにしてもらいました。 この時点でプロダクト側のフロントエンド設計も進んでいたため、ESLint やコンポーネント設計、ライブラリなどを流用し、デザインプロジェクト用に最適化させます。 4.Next.js の設計 実際にエンジニアがプロダクトを実装する際には色々なことを検討する必要があると思いますが、デザインツールとして使用する際には、逆にそこまでガチガチにしてしまうと実装に工数がかかりすぎてしまうので「割り切り」が必要になります。私が実装した際の環境は以下のようなものです。 TypeScript は入れない。要件が固まりきっていない状態で型定義をやり始めると修正に時間がかかりすぎるため。 非同期通信処理も入れない。データがほしければローカルに json ファイルを配置しておく。 デザイン側のソースコードの汚さはあまり気にしない。プロダクト版を作成するときにフロントエンドエンジニアがきれいに作り直してくれる。 コンポーネント設計を意識する。共通コンポーネントとして使用する汎用的なものは先に洗い出しておく。 テストコードは書かない。そこまでページ数が多くない上、上記のような割り切りをしているので複雑性も極端に上がらない。 Google Chrome 最新版のみ対応とする。他のブラウザは無視する。 (昨今のフロントエンド開発の流れと真逆、、、) 5.デザインルール設計 続いてデザインルールの設計を行います。 theme.js ファイルを作成し、以下を定義します。この時点で定義が完全にできていることは無いと思うので、分かる範囲で書いていきます。最終的に、不要なものを消したり、一緒にできるものは統合して定義を減らしていきます。 各コンポーネントで padding や margin の余白を数値で指定したり、色味のカラーコドをベタ打ちせず、必ず theme ファイルから値を引っ張ってくるようにします。そうすると、修正が容易になる上、あとからどこで何が使われているかを把握しやすくなります。 ■theme 内に記述する内容のイメージ fontFamily// fontFamily を定義 colors// カラーコードの一覧 spaces // 4/8/16 など余白に使う数字を定義。 fontSizes // fontSize を定義 lineHeight // lineHeight を定義 fontWeight // fontWeight を定義。 boxShadow // ドロップシャドウを使用するなら定義 6.コンポーネント設計 続いて、コンポーネントとコンポーネントに必要な props を洗い出します。 世の中には優秀な UI フレームワークが複数存在していますのでそういったものを参考にします。そういったものはほとんど同じようなコンポーネント設計になっているのでコンポーネントの分け方や受け取る props などを参考にすると作業が捗ります。 Ant Design https://ant.design/ Material-UI https://material-ui.com/ Element https://element.eleme.io/#/en-US ここで気をつけたいのは、コンポーネントの数を極力減らすように努力することです。 同一機能の別コンポーネントが複数できてしまうと、今後の機能拡張時に、どのコンポーネントを使うか迷うことになります。ほとんどのエンジニアやデザイナーにとって、コンポーネント選びで迷うことは時間の無駄です。選択肢は極力減らす努力をし、減らせないようなら使用する場所を明確に定義する必要があります。 例えば component/tab1/ component/tab2/ component/tab3/ のようにタブコンポーネントが複数あると、あとから見たときにどれを使えばいいかわからなくなりますよね。 これを許容してしまうと、知らぬ間に component/tab4/ ができあがっていることでしょう。 7.実装 まずは大枠のページテンプレートを制作します。その後、小さいコンポーネントから順に作り上げていき、ページテンプレートに配置していきます。コンポーネント化ができていれば、見た目の変更はあとから行えるので、まずは page 内に配置し、機能することを目指します。 この時点で、デザインを細部まで作り込んだとしても、結局全体を見渡してから細かく調整をかけていくと思うので、そこまでセンシティブにならずに行っていきます。 8.確認・ヒアリング・修正の繰り返し 見た目が完全にできていない状態で、確認観点を絞って、PM や、ディレクター、実際に業務で使う方々にチェックしてもらいフィードバックを受けます。 徐々にブラッシュアップしていき、完成を目指します。 デザイン中には常に以下を意識して作業することで、無駄なものを介在させない設計を目指します。 コンポーネントを共通化できないか 色数を減らせないか fontSize や lineheight などの定義を減らせないか 9.各種資料の作成 作っているデザインではエラー処理などすべてを表現しきれないので、補足資料として別途スプレッドシートなどにまとめていきます。 また、実際のコンポーネントと想定している props、実装時の注意事項などを記載した UI コンポーネント集ページを制作し、フロントエンドエンジニアと共有します。 Storybook での共有も検討しましたが、受け渡す props の想定、エンジニアへの指示、要件の補足を記載していくだけですので、Storybook ほどの機能は不要と考え、Next.js 内にシンプルな Page を作り、そこに記述する方法を選択しました。 また、デザインの設計ルールも資料化し、最終的には各種資料と、制作したコード、S3 にアップされている URL を成果物としてエンジニアに実装をしていってもらいデザインのフェーズを完了させます。 React でデザインした場合のメリット 忠実度の高いモックアップが制作できる プロトタイプツールは数多くあれど、実装にまさる忠実度の高さなし。 最近は Figma の AutoLayout や XD のスタックなど、便利な機能も登場してきていますし、プロトタイピングに関しても様々なアクションが設定できるので、非常に便利になってきました。ただ、それでも CSS や JS の表現力にはまだ届かない部分も多いかなと感じています。 ボタンを押したとき、特定の <select/> の <option/> が選択されたとき、複数条件下でのみ表示させるもの、ウインドウサイズが小さくなったときの表示など、デザインツールで実装するにはやや面倒な箇所も、コードベースなら対応可能で、デザインファイルと実装されたページでの印象差も起こりづらいです。 実際に操作できる環境を渡すことで高い精度のフィードバックをもらえる 様々なリテラシーのユーザーが使用するサービスであるからこそ、よりリアルなプロトタイプを使用し、ミスコミュニケーションを減らせました。 結果論ですが、新型コロナウィルスによって、コミュニケーションを取りにくい状況が続きましたが、挙動を忠実に再現しているので、精度の高い意見を聞けたのは良かったです。 プロダクト版のフロントエンドの実装時に、こちらの意図が伝わりやすい fontSize や space、color を theme.js ファイルにまとめておき、そこからコンポーネント側では theme 側から読み込むようにしておけば、デザインルールが把握しやすくなります。また、CSS がすでに記述されているので、プロダクト版への移植も可能となり、「デザインファイルと実装でデザインが違う」が起こりにくくなります。 Git やエディタの恩恵をフルに受けられる 一旦別ブランチでデザイン案を作る、作ったブランチの commit から cherry-pick する、過去の log を見る、特定の commit に戻るなど、Git の恩恵をフルに受けられます。また、文字列の一括検索や置換が可能なので、色味を一気に置き換えたい、どこで使われているかを探したい場合などかなり重宝しました。 とはいえいいことばかりではなかった。。。 ちょっと要素の位置を変える、などはデザインファイルのほうが全然楽。コードベースだと CSS と HTML 構造自体を書き換えないといけない React を理解していないと、動かなくなったりした時に、修正で時間を余計に使ってしまう 他のデザイナーに引き継ぎしずらい など、通常のデザインファイルでは起こらないようなデメリットもありました。 結局の所プロジェクトによって向き不向きはあります。 個人的には社内の管理システム系のように、一般的なコンポーネントを組み合わせて、色々なデータを表示する必要があるサイト制作に向いているかなと思います。 逆に、特殊なコンポーネントを量産するケースや、LP のようにグラフィック要素が多くなってくるとデザインツールのほうがはかどります。 プロジェクトの性格に応じて最適なデザイン方法を選んでいきたいですね。 デザイナーだけどコードも書きたい方や、一緒にプルリク送ってくれるデザイナーの方いらっしゃれば、ぜひメドレーで一緒に働きましょう〜 募集の一覧 | 株式会社メドレー メドレーの採用情報はこちらからご確認ください。 www.medley.jp
メドレーのデザイナー酒井です。最近、 JobMedley から CLINICS に異動しました。 自分はデザインはもちろん、HTML/CSS/JS 実装してプルリク送ったりしているちょっとフロントエンド実装領域に軸足が寄ったタイプのデザイナーです。 ここでは以前所属していた JobMedley 事業部の話をさせていただきます。 当時、JobMedley の社内システムのリニューアルプロジェクトにデザイナーとして参加していました。通常、デザイナーがデザインをするときには Skecth や Figma のようなデザインツールを利用するのが一般的かと思います。 弊社でも基本的にはデザインツールでデザインを行うことが多いのですが、プロジェクトによっては、よりリアルなモックアップが必要なため、デザイナー自身がコーディングでデザインを行い、ブラッシュアップしていくことがあります。その後、フロントエンド実装者が、デザイナーが作ったデザインを参考に、しっかりと設計されたもので作り直します。 今回のリニューアルプロジェクトのデザイン・モックアップの制作では、Figma や Sketch などのデザインツールは使用せず、React でコーディング行い、デザインを制作しています。ここが特殊な制作フローになると思うので、このエントリでは React をデザインツールとして使ったときの流れとメリット・デメリット、ちょっとニッチなポイントに絞ってお話していきます。 デザインの流れ 1.まずは React を勉強する 元々受託制作会社でデザイナーをやっていた時代に Vue.js での開発経験はありましたが、React は今回が初めてでした。そのため、一旦公式チュートリアルを一通り読み、Google などで調べつつ、基礎知識のインプットすることからはじめました。 2.ワイヤーフレームを作る さすがにワイヤーフレーム無しでコード実装には入れないので、ここでは Figma などのツールを使います。ワイヤーフレームを作り、要件定義を進めていきますが、デザインに関してもある程度のあたりを付けていきます。 3.開発環境構築 今回は Next.js で制作を行っています。 そもそも、プロダクトの実装で Next.js を使用することが決まっていたので、デザイン側も Next.js を採用しましたが、結果的に良かったなと感じています。 Next.js で作っておけば、めんどくさい router の設定やデザイナーが苦手な webpack の config を記述しなくてすみます。 また、 next build && next export で静的な HTML ファイルとして書き出されるため、サーバがあればすぐに共有が可能です。今回はエンジニアさんに、develop ブランチに merge されると、 next build && next export が走り、自動で Amazon S3 に静的ファイルをデプロイされるようにしてもらいました。 この時点でプロダクト側のフロントエンド設計も進んでいたため、ESLint やコンポーネント設計、ライブラリなどを流用し、デザインプロジェクト用に最適化させます。 4.Next.js の設計 実際にエンジニアがプロダクトを実装する際には色々なことを検討する必要があると思いますが、デザインツールとして使用する際には、逆にそこまでガチガチにしてしまうと実装に工数がかかりすぎてしまうので「割り切り」が必要になります。私が実装した際の環境は以下のようなものです。 TypeScript は入れない。要件が固まりきっていない状態で型定義をやり始めると修正に時間がかかりすぎるため。 非同期通信処理も入れない。データがほしければローカルに json ファイルを配置しておく。 デザイン側のソースコードの汚さはあまり気にしない。プロダクト版を作成するときにフロントエンドエンジニアがきれいに作り直してくれる。 コンポーネント設計を意識する。共通コンポーネントとして使用する汎用的なものは先に洗い出しておく。 テストコードは書かない。そこまでページ数が多くない上、上記のような割り切りをしているので複雑性も極端に上がらない。 Google Chrome 最新版のみ対応とする。他のブラウザは無視する。 (昨今のフロントエンド開発の流れと真逆、、、) 5.デザインルール設計 続いてデザインルールの設計を行います。 theme.js ファイルを作成し、以下を定義します。この時点で定義が完全にできていることは無いと思うので、分かる範囲で書いていきます。最終的に、不要なものを消したり、一緒にできるものは統合して定義を減らしていきます。 各コンポーネントで padding や margin の余白を数値で指定したり、色味のカラーコドをベタ打ちせず、必ず theme ファイルから値を引っ張ってくるようにします。そうすると、修正が容易になる上、あとからどこで何が使われているかを把握しやすくなります。 ■theme 内に記述する内容のイメージ fontFamily// fontFamily を定義 colors// カラーコードの一覧 spaces // 4/8/16 など余白に使う数字を定義。 fontSizes // fontSize を定義 lineHeight // lineHeight を定義 fontWeight // fontWeight を定義。 boxShadow // ドロップシャドウを使用するなら定義 6.コンポーネント設計 続いて、コンポーネントとコンポーネントに必要な props を洗い出します。 世の中には優秀な UI フレームワークが複数存在していますのでそういったものを参考にします。そういったものはほとんど同じようなコンポーネント設計になっているのでコンポーネントの分け方や受け取る props などを参考にすると作業が捗ります。 Ant Design https://ant.design/ Material-UI https://material-ui.com/ Element https://element.eleme.io/#/en-US ここで気をつけたいのは、コンポーネントの数を極力減らすように努力することです。 同一機能の別コンポーネントが複数できてしまうと、今後の機能拡張時に、どのコンポーネントを使うか迷うことになります。ほとんどのエンジニアやデザイナーにとって、コンポーネント選びで迷うことは時間の無駄です。選択肢は極力減らす努力をし、減らせないようなら使用する場所を明確に定義する必要があります。 例えば component/tab1/ component/tab2/ component/tab3/ のようにタブコンポーネントが複数あると、あとから見たときにどれを使えばいいかわからなくなりますよね。 これを許容してしまうと、知らぬ間に component/tab4/ ができあがっていることでしょう。 7.実装 まずは大枠のページテンプレートを制作します。その後、小さいコンポーネントから順に作り上げていき、ページテンプレートに配置していきます。コンポーネント化ができていれば、見た目の変更はあとから行えるので、まずは page 内に配置し、機能することを目指します。 この時点で、デザインを細部まで作り込んだとしても、結局全体を見渡してから細かく調整をかけていくと思うので、そこまでセンシティブにならずに行っていきます。 8.確認・ヒアリング・修正の繰り返し 見た目が完全にできていない状態で、確認観点を絞って、PM や、ディレクター、実際に業務で使う方々にチェックしてもらいフィードバックを受けます。 徐々にブラッシュアップしていき、完成を目指します。 デザイン中には常に以下を意識して作業することで、無駄なものを介在させない設計を目指します。 コンポーネントを共通化できないか 色数を減らせないか fontSize や lineheight などの定義を減らせないか 9.各種資料の作成 作っているデザインではエラー処理などすべてを表現しきれないので、補足資料として別途スプレッドシートなどにまとめていきます。 また、実際のコンポーネントと想定している props、実装時の注意事項などを記載した UI コンポーネント集ページを制作し、フロントエンドエンジニアと共有します。 Storybook での共有も検討しましたが、受け渡す props の想定、エンジニアへの指示、要件の補足を記載していくだけですので、Storybook ほどの機能は不要と考え、Next.js 内にシンプルな Page を作り、そこに記述する方法を選択しました。 また、デザインの設計ルールも資料化し、最終的には各種資料と、制作したコード、S3 にアップされている URL を成果物としてエンジニアに実装をしていってもらいデザインのフェーズを完了させます。 React でデザインした場合のメリット 忠実度の高いモックアップが制作できる プロトタイプツールは数多くあれど、実装にまさる忠実度の高さなし。 最近は Figma の AutoLayout や XD のスタックなど、便利な機能も登場してきていますし、プロトタイピングに関しても様々なアクションが設定できるので、非常に便利になってきました。ただ、それでも CSS や JS の表現力にはまだ届かない部分も多いかなと感じています。 ボタンを押したとき、特定の <select/> の <option/> が選択されたとき、複数条件下でのみ表示させるもの、ウインドウサイズが小さくなったときの表示など、デザインツールで実装するにはやや面倒な箇所も、コードベースなら対応可能で、デザインファイルと実装されたページでの印象差も起こりづらいです。 実際に操作できる環境を渡すことで高い精度のフィードバックをもらえる 様々なリテラシーのユーザーが使用するサービスであるからこそ、よりリアルなプロトタイプを使用し、ミスコミュニケーションを減らせました。 結果論ですが、新型コロナウィルスによって、コミュニケーションを取りにくい状況が続きましたが、挙動を忠実に再現しているので、精度の高い意見を聞けたのは良かったです。 プロダクト版のフロントエンドの実装時に、こちらの意図が伝わりやすい fontSize や space、color を theme.js ファイルにまとめておき、そこからコンポーネント側では theme 側から読み込むようにしておけば、デザインルールが把握しやすくなります。また、CSS がすでに記述されているので、プロダクト版への移植も可能となり、「デザインファイルと実装でデザインが違う」が起こりにくくなります。 Git やエディタの恩恵をフルに受けられる 一旦別ブランチでデザイン案を作る、作ったブランチの commit から cherry-pick する、過去の log を見る、特定の commit に戻るなど、Git の恩恵をフルに受けられます。また、文字列の一括検索や置換が可能なので、色味を一気に置き換えたい、どこで使われているかを探したい場合などかなり重宝しました。 とはいえいいことばかりではなかった。。。 ちょっと要素の位置を変える、などはデザインファイルのほうが全然楽。コードベースだと CSS と HTML 構造自体を書き換えないといけない React を理解していないと、動かなくなったりした時に、修正で時間を余計に使ってしまう 他のデザイナーに引き継ぎしずらい など、通常のデザインファイルでは起こらないようなデメリットもありました。 結局の所プロジェクトによって向き不向きはあります。 個人的には社内の管理システム系のように、一般的なコンポーネントを組み合わせて、色々なデータを表示する必要があるサイト制作に向いているかなと思います。 逆に、特殊なコンポーネントを量産するケースや、LP のようにグラフィック要素が多くなってくるとデザインツールのほうがはかどります。 プロジェクトの性格に応じて最適なデザイン方法を選んでいきたいですね。 デザイナーだけどコードも書きたい方や、一緒にプルリク送ってくれるデザイナーの方いらっしゃれば、ぜひメドレーで一緒に働きましょう〜 募集の一覧 | 株式会社メドレー メドレーの採用情報はこちらからご確認ください。 www.medley.jp
メドレーのデザイナー酒井です。最近、 JobMedley から CLINICS に異動しました。 自分はデザインはもちろん、HTML/CSS/JS 実装してプルリク送ったりしているちょっとフロントエンド実装領域に軸足が寄ったタイプのデザイナーです。 ここでは以前所属していた JobMedley 事業部の話をさせていただきます。 当時、JobMedley の社内システムのリニューアルプロジェクトにデザイナーとして参加していました。通常、デザイナーがデザインをするときには Skecth や Figma のようなデザインツールを利用するのが一般的かと思います。 弊社でも基本的にはデザインツールでデザインを行うことが多いのですが、プロジェクトによっては、よりリアルなモックアップが必要なため、デザイナー自身がコーディングでデザインを行い、ブラッシュアップしていくことがあります。その後、フロントエンド実装者が、デザイナーが作ったデザインを参考に、しっかりと設計されたもので作り直します。 今回のリニューアルプロジェクトのデザイン・モックアップの制作では、Figma や Sketch などのデザインツールは使用せず、React でコーディング行い、デザインを制作しています。ここが特殊な制作フローになると思うので、このエントリでは React をデザインツールとして使ったときの流れとメリット・デメリット、ちょっとニッチなポイントに絞ってお話していきます。 デザインの流れ 1.まずは React を勉強する 元々受託制作会社でデザイナーをやっていた時代に Vue.js での開発経験はありましたが、React は今回が初めてでした。そのため、一旦公式チュートリアルを一通り読み、Google などで調べつつ、基礎知識のインプットすることからはじめました。 2.ワイヤーフレームを作る さすがにワイヤーフレーム無しでコード実装には入れないので、ここでは Figma などのツールを使います。ワイヤーフレームを作り、要件定義を進めていきますが、デザインに関してもある程度のあたりを付けていきます。 3.開発環境構築 今回は Next.js で制作を行っています。 そもそも、プロダクトの実装で Next.js を使用することが決まっていたので、デザイン側も Next.js を採用しましたが、結果的に良かったなと感じています。 Next.js で作っておけば、めんどくさい router の設定やデザイナーが苦手な webpack の config を記述しなくてすみます。 また、 next build && next export で静的な HTML ファイルとして書き出されるため、サーバがあればすぐに共有が可能です。今回はエンジニアさんに、develop ブランチに merge されると、 next build && next export が走り、自動で Amazon S3 に静的ファイルをデプロイされるようにしてもらいました。 この時点でプロダクト側のフロントエンド設計も進んでいたため、ESLint やコンポーネント設計、ライブラリなどを流用し、デザインプロジェクト用に最適化させます。 4.Next.js の設計 実際にエンジニアがプロダクトを実装する際には色々なことを検討する必要があると思いますが、デザインツールとして使用する際には、逆にそこまでガチガチにしてしまうと実装に工数がかかりすぎてしまうので「割り切り」が必要になります。私が実装した際の環境は以下のようなものです。 TypeScript は入れない。要件が固まりきっていない状態で型定義をやり始めると修正に時間がかかりすぎるため。 非同期通信処理も入れない。データがほしければローカルに json ファイルを配置しておく。 デザイン側のソースコードの汚さはあまり気にしない。プロダクト版を作成するときにフロントエンドエンジニアがきれいに作り直してくれる。 コンポーネント設計を意識する。共通コンポーネントとして使用する汎用的なものは先に洗い出しておく。 テストコードは書かない。そこまでページ数が多くない上、上記のような割り切りをしているので複雑性も極端に上がらない。 Google Chrome 最新版のみ対応とする。他のブラウザは無視する。 (昨今のフロントエンド開発の流れと真逆、、、) 5.デザインルール設計 続いてデザインルールの設計を行います。 theme.js ファイルを作成し、以下を定義します。この時点で定義が完全にできていることは無いと思うので、分かる範囲で書いていきます。最終的に、不要なものを消したり、一緒にできるものは統合して定義を減らしていきます。 各コンポーネントで padding や margin の余白を数値で指定したり、色味のカラーコドをベタ打ちせず、必ず theme ファイルから値を引っ張ってくるようにします。そうすると、修正が容易になる上、あとからどこで何が使われているかを把握しやすくなります。 ■theme 内に記述する内容のイメージ fontFamily// fontFamily を定義 colors// カラーコードの一覧 spaces // 4/8/16 など余白に使う数字を定義。 fontSizes // fontSize を定義 lineHeight // lineHeight を定義 fontWeight // fontWeight を定義。 boxShadow // ドロップシャドウを使用するなら定義 6.コンポーネント設計 続いて、コンポーネントとコンポーネントに必要な props を洗い出します。 世の中には優秀な UI フレームワークが複数存在していますのでそういったものを参考にします。そういったものはほとんど同じようなコンポーネント設計になっているのでコンポーネントの分け方や受け取る props などを参考にすると作業が捗ります。 Ant Design https://ant.design/ Material-UI https://material-ui.com/ Element https://element.eleme.io/#/en-US ここで気をつけたいのは、コンポーネントの数を極力減らすように努力することです。 同一機能の別コンポーネントが複数できてしまうと、今後の機能拡張時に、どのコンポーネントを使うか迷うことになります。ほとんどのエンジニアやデザイナーにとって、コンポーネント選びで迷うことは時間の無駄です。選択肢は極力減らす努力をし、減らせないようなら使用する場所を明確に定義する必要があります。 例えば component/tab1/ component/tab2/ component/tab3/ のようにタブコンポーネントが複数あると、あとから見たときにどれを使えばいいかわからなくなりますよね。 これを許容してしまうと、知らぬ間に component/tab4/ ができあがっていることでしょう。 7.実装 まずは大枠のページテンプレートを制作します。その後、小さいコンポーネントから順に作り上げていき、ページテンプレートに配置していきます。コンポーネント化ができていれば、見た目の変更はあとから行えるので、まずは page 内に配置し、機能することを目指します。 この時点で、デザインを細部まで作り込んだとしても、結局全体を見渡してから細かく調整をかけていくと思うので、そこまでセンシティブにならずに行っていきます。 8.確認・ヒアリング・修正の繰り返し 見た目が完全にできていない状態で、確認観点を絞って、PM や、ディレクター、実際に業務で使う方々にチェックしてもらいフィードバックを受けます。 徐々にブラッシュアップしていき、完成を目指します。 デザイン中には常に以下を意識して作業することで、無駄なものを介在させない設計を目指します。 コンポーネントを共通化できないか 色数を減らせないか fontSize や lineheight などの定義を減らせないか 9.各種資料の作成 作っているデザインではエラー処理などすべてを表現しきれないので、補足資料として別途スプレッドシートなどにまとめていきます。 また、実際のコンポーネントと想定している props、実装時の注意事項などを記載した UI コンポーネント集ページを制作し、フロントエンドエンジニアと共有します。 Storybook での共有も検討しましたが、受け渡す props の想定、エンジニアへの指示、要件の補足を記載していくだけですので、Storybook ほどの機能は不要と考え、Next.js 内にシンプルな Page を作り、そこに記述する方法を選択しました。 また、デザインの設計ルールも資料化し、最終的には各種資料と、制作したコード、S3 にアップされている URL を成果物としてエンジニアに実装をしていってもらいデザインのフェーズを完了させます。 React でデザインした場合のメリット 忠実度の高いモックアップが制作できる プロトタイプツールは数多くあれど、実装にまさる忠実度の高さなし。 最近は Figma の AutoLayout や XD のスタックなど、便利な機能も登場してきていますし、プロトタイピングに関しても様々なアクションが設定できるので、非常に便利になってきました。ただ、それでも CSS や JS の表現力にはまだ届かない部分も多いかなと感じています。 ボタンを押したとき、特定の <select/> の <option/> が選択されたとき、複数条件下でのみ表示させるもの、ウインドウサイズが小さくなったときの表示など、デザインツールで実装するにはやや面倒な箇所も、コードベースなら対応可能で、デザインファイルと実装されたページでの印象差も起こりづらいです。 実際に操作できる環境を渡すことで高い精度のフィードバックをもらえる 様々なリテラシーのユーザーが使用するサービスであるからこそ、よりリアルなプロトタイプを使用し、ミスコミュニケーションを減らせました。 結果論ですが、新型コロナウィルスによって、コミュニケーションを取りにくい状況が続きましたが、挙動を忠実に再現しているので、精度の高い意見を聞けたのは良かったです。 プロダクト版のフロントエンドの実装時に、こちらの意図が伝わりやすい fontSize や space、color を theme.js ファイルにまとめておき、そこからコンポーネント側では theme 側から読み込むようにしておけば、デザインルールが把握しやすくなります。また、CSS がすでに記述されているので、プロダクト版への移植も可能となり、「デザインファイルと実装でデザインが違う」が起こりにくくなります。 Git やエディタの恩恵をフルに受けられる 一旦別ブランチでデザイン案を作る、作ったブランチの commit から cherry-pick する、過去の log を見る、特定の commit に戻るなど、Git の恩恵をフルに受けられます。また、文字列の一括検索や置換が可能なので、色味を一気に置き換えたい、どこで使われているかを探したい場合などかなり重宝しました。 とはいえいいことばかりではなかった。。。 ちょっと要素の位置を変える、などはデザインファイルのほうが全然楽。コードベースだと CSS と HTML 構造自体を書き換えないといけない React を理解していないと、動かなくなったりした時に、修正で時間を余計に使ってしまう 他のデザイナーに引き継ぎしずらい など、通常のデザインファイルでは起こらないようなデメリットもありました。 結局の所プロジェクトによって向き不向きはあります。 個人的には社内の管理システム系のように、一般的なコンポーネントを組み合わせて、色々なデータを表示する必要があるサイト制作に向いているかなと思います。 逆に、特殊なコンポーネントを量産するケースや、LP のようにグラフィック要素が多くなってくるとデザインツールのほうがはかどります。 プロジェクトの性格に応じて最適なデザイン方法を選んでいきたいですね。 デザイナーだけどコードも書きたい方や、一緒にプルリク送ってくれるデザイナーの方いらっしゃれば、ぜひメドレーで一緒に働きましょう〜 https://www.medley.jp/jobs/designer-new.html
メドレーのデザイナー酒井です。最近、 JobMedley から CLINICS に異動しました。 自分はデザインはもちろん、HTML/CSS/JS 実装してプルリク送ったりしているちょっとフロントエンド実装領域に軸足が寄ったタイプのデザイナーです。 ここでは以前所属していた JobMedley 事業部の話をさせていただきます。 当時、JobMedley の社内システムのリニューアルプロジェクトにデザイナーとして参加していました。通常、デザイナーがデザインをするときには Skecth や Figma のようなデザインツールを利用するのが一般的かと思います。 弊社でも基本的にはデザインツールでデザインを行うことが多いのですが、プロジェクトによっては、よりリアルなモックアップが必要なため、デザイナー自身がコーディングでデザインを行い、ブラッシュアップしていくことがあります。その後、フロントエンド実装者が、デザイナーが作ったデザインを参考に、しっかりと設計されたもので作り直します。 今回のリニューアルプロジェクトのデザイン・モックアップの制作では、Figma や Sketch などのデザインツールは使用せず、React でコーディング行い、デザインを制作しています。ここが特殊な制作フローになると思うので、このエントリでは React をデザインツールとして使ったときの流れとメリット・デメリット、ちょっとニッチなポイントに絞ってお話していきます。 デザインの流れ 1.まずは React を勉強する 元々受託制作会社でデザイナーをやっていた時代に Vue.js での開発経験はありましたが、React は今回が初めてでした。そのため、一旦公式チュートリアルを一通り読み、Google などで調べつつ、基礎知識のインプットすることからはじめました。 2.ワイヤーフレームを作る さすがにワイヤーフレーム無しでコード実装には入れないので、ここでは Figma などのツールを使います。ワイヤーフレームを作り、要件定義を進めていきますが、デザインに関してもある程度のあたりを付けていきます。 3.開発環境構築 今回は Next.js で制作を行っています。 そもそも、プロダクトの実装で Next.js を使用することが決まっていたので、デザイン側も Next.js を採用しましたが、結果的に良かったなと感じています。 Next.js で作っておけば、めんどくさい router の設定やデザイナーが苦手な webpack の config を記述しなくてすみます。 また、 next build && next export で静的な HTML ファイルとして書き出されるため、サーバがあればすぐに共有が可能です。今回はエンジニアさんに、develop ブランチに merge されると、 next build && next export が走り、自動で Amazon S3 に静的ファイルをデプロイされるようにしてもらいました。 この時点でプロダクト側のフロントエンド設計も進んでいたため、ESLint やコンポーネント設計、ライブラリなどを流用し、デザインプロジェクト用に最適化させます。 4.Next.js の設計 実際にエンジニアがプロダクトを実装する際には色々なことを検討する必要があると思いますが、デザインツールとして使用する際には、逆にそこまでガチガチにしてしまうと実装に工数がかかりすぎてしまうので「割り切り」が必要になります。私が実装した際の環境は以下のようなものです。 TypeScript は入れない。要件が固まりきっていない状態で型定義をやり始めると修正に時間がかかりすぎるため。 非同期通信処理も入れない。データがほしければローカルに json ファイルを配置しておく。 デザイン側のソースコードの汚さはあまり気にしない。プロダクト版を作成するときにフロントエンドエンジニアがきれいに作り直してくれる。 コンポーネント設計を意識する。共通コンポーネントとして使用する汎用的なものは先に洗い出しておく。 テストコードは書かない。そこまでページ数が多くない上、上記のような割り切りをしているので複雑性も極端に上がらない。 Google Chrome 最新版のみ対応とする。他のブラウザは無視する。 (昨今のフロントエンド開発の流れと真逆、、、) 5.デザインルール設計 続いてデザインルールの設計を行います。 theme.js ファイルを作成し、以下を定義します。この時点で定義が完全にできていることは無いと思うので、分かる範囲で書いていきます。最終的に、不要なものを消したり、一緒にできるものは統合して定義を減らしていきます。 各コンポーネントで padding や margin の余白を数値で指定したり、色味のカラーコドをベタ打ちせず、必ず theme ファイルから値を引っ張ってくるようにします。そうすると、修正が容易になる上、あとからどこで何が使われているかを把握しやすくなります。 ■theme 内に記述する内容のイメージ fontFamily// fontFamily を定義 colors// カラーコードの一覧 spaces // 4/8/16 など余白に使う数字を定義。 fontSizes // fontSize を定義 lineHeight // lineHeight を定義 fontWeight // fontWeight を定義。 boxShadow // ドロップシャドウを使用するなら定義 6.コンポーネント設計 続いて、コンポーネントとコンポーネントに必要な props を洗い出します。 世の中には優秀な UI フレームワークが複数存在していますのでそういったものを参考にします。そういったものはほとんど同じようなコンポーネント設計になっているのでコンポーネントの分け方や受け取る props などを参考にすると作業が捗ります。 Ant Design https://ant.design/ Material-UI https://material-ui.com/ Element https://element.eleme.io/#/en-US ここで気をつけたいのは、コンポーネントの数を極力減らすように努力することです。 同一機能の別コンポーネントが複数できてしまうと、今後の機能拡張時に、どのコンポーネントを使うか迷うことになります。ほとんどのエンジニアやデザイナーにとって、コンポーネント選びで迷うことは時間の無駄です。選択肢は極力減らす努力をし、減らせないようなら使用する場所を明確に定義する必要があります。 例えば component/tab1/ component/tab2/ component/tab3/ のようにタブコンポーネントが複数あると、あとから見たときにどれを使えばいいかわからなくなりますよね。 これを許容してしまうと、知らぬ間に component/tab4/ ができあがっていることでしょう。 7.実装 まずは大枠のページテンプレートを制作します。その後、小さいコンポーネントから順に作り上げていき、ページテンプレートに配置していきます。コンポーネント化ができていれば、見た目の変更はあとから行えるので、まずは page 内に配置し、機能することを目指します。 この時点で、デザインを細部まで作り込んだとしても、結局全体を見渡してから細かく調整をかけていくと思うので、そこまでセンシティブにならずに行っていきます。 8.確認・ヒアリング・修正の繰り返し 見た目が完全にできていない状態で、確認観点を絞って、PM や、ディレクター、実際に業務で使う方々にチェックしてもらいフィードバックを受けます。 徐々にブラッシュアップしていき、完成を目指します。 デザイン中には常に以下を意識して作業することで、無駄なものを介在させない設計を目指します。 コンポーネントを共通化できないか 色数を減らせないか fontSize や lineheight などの定義を減らせないか 9.各種資料の作成 作っているデザインではエラー処理などすべてを表現しきれないので、補足資料として別途スプレッドシートなどにまとめていきます。 また、実際のコンポーネントと想定している props、実装時の注意事項などを記載した UI コンポーネント集ページを制作し、フロントエンドエンジニアと共有します。 Storybook での共有も検討しましたが、受け渡す props の想定、エンジニアへの指示、要件の補足を記載していくだけですので、Storybook ほどの機能は不要と考え、Next.js 内にシンプルな Page を作り、そこに記述する方法を選択しました。 また、デザインの設計ルールも資料化し、最終的には各種資料と、制作したコード、S3 にアップされている URL を成果物としてエンジニアに実装をしていってもらいデザインのフェーズを完了させます。 React でデザインした場合のメリット 忠実度の高いモックアップが制作できる プロトタイプツールは数多くあれど、実装にまさる忠実度の高さなし。 最近は Figma の AutoLayout や XD のスタックなど、便利な機能も登場してきていますし、プロトタイピングに関しても様々なアクションが設定できるので、非常に便利になってきました。ただ、それでも CSS や JS の表現力にはまだ届かない部分も多いかなと感じています。 ボタンを押したとき、特定の <select/> の <option/> が選択されたとき、複数条件下でのみ表示させるもの、ウインドウサイズが小さくなったときの表示など、デザインツールで実装するにはやや面倒な箇所も、コードベースなら対応可能で、デザインファイルと実装されたページでの印象差も起こりづらいです。 実際に操作できる環境を渡すことで高い精度のフィードバックをもらえる 様々なリテラシーのユーザーが使用するサービスであるからこそ、よりリアルなプロトタイプを使用し、ミスコミュニケーションを減らせました。 結果論ですが、新型コロナウィルスによって、コミュニケーションを取りにくい状況が続きましたが、挙動を忠実に再現しているので、精度の高い意見を聞けたのは良かったです。 プロダクト版のフロントエンドの実装時に、こちらの意図が伝わりやすい fontSize や space、color を theme.js ファイルにまとめておき、そこからコンポーネント側では theme 側から読み込むようにしておけば、デザインルールが把握しやすくなります。また、CSS がすでに記述されているので、プロダクト版への移植も可能となり、「デザインファイルと実装でデザインが違う」が起こりにくくなります。 Git やエディタの恩恵をフルに受けられる 一旦別ブランチでデザイン案を作る、作ったブランチの commit から cherry-pick する、過去の log を見る、特定の commit に戻るなど、Git の恩恵をフルに受けられます。また、文字列の一括検索や置換が可能なので、色味を一気に置き換えたい、どこで使われているかを探したい場合などかなり重宝しました。 とはいえいいことばかりではなかった。。。 ちょっと要素の位置を変える、などはデザインファイルのほうが全然楽。コードベースだと CSS と HTML 構造自体を書き換えないといけない React を理解していないと、動かなくなったりした時に、修正で時間を余計に使ってしまう 他のデザイナーに引き継ぎしずらい など、通常のデザインファイルでは起こらないようなデメリットもありました。 結局の所プロジェクトによって向き不向きはあります。 個人的には社内の管理システム系のように、一般的なコンポーネントを組み合わせて、色々なデータを表示する必要があるサイト制作に向いているかなと思います。 逆に、特殊なコンポーネントを量産するケースや、LP のようにグラフィック要素が多くなってくるとデザインツールのほうがはかどります。 プロジェクトの性格に応じて最適なデザイン方法を選んでいきたいですね。 デザイナーだけどコードも書きたい方や、一緒にプルリク送ってくれるデザイナーの方いらっしゃれば、ぜひメドレーで一緒に働きましょう〜 募集の一覧 | 株式会社メドレー メドレーの採用情報はこちらからご確認ください。 www.medley.jp
メドレーのデザイナー酒井です。最近、 JobMedley から CLINICS に異動しました。 自分はデザインはもちろん、HTML/CSS/JS 実装してプルリク送ったりしているちょっとフロントエンド実装領域に軸足が寄ったタイプのデザイナーです。 ここでは以前所属していた JobMedley 事業部の話をさせていただきます。 当時、JobMedley の社内システムのリニューアルプロジェクトにデザイナーとして参加していました。通常、デザイナーがデザインをするときには Skecth や Figma のようなデザインツールを利用するのが一般的かと思います。 弊社でも基本的にはデザインツールでデザインを行うことが多いのですが、プロジェクトによっては、よりリアルなモックアップが必要なため、デザイナー自身がコーディングでデザインを行い、ブラッシュアップしていくことがあります。その後、フロントエンド実装者が、デザイナーが作ったデザインを参考に、しっかりと設計されたもので作り直します。 今回のリニューアルプロジェクトのデザイン・モックアップの制作では、Figma や Sketch などのデザインツールは使用せず、React でコーディング行い、デザインを制作しています。ここが特殊な制作フローになると思うので、このエントリでは React をデザインツールとして使ったときの流れとメリット・デメリット、ちょっとニッチなポイントに絞ってお話していきます。 デザインの流れ 1.まずは React を勉強する 元々受託制作会社でデザイナーをやっていた時代に Vue.js での開発経験はありましたが、React は今回が初めてでした。そのため、一旦公式チュートリアルを一通り読み、Google などで調べつつ、基礎知識のインプットすることからはじめました。 2.ワイヤーフレームを作る さすがにワイヤーフレーム無しでコード実装には入れないので、ここでは Figma などのツールを使います。ワイヤーフレームを作り、要件定義を進めていきますが、デザインに関してもある程度のあたりを付けていきます。 3.開発環境構築 今回は Next.js で制作を行っています。 そもそも、プロダクトの実装で Next.js を使用することが決まっていたので、デザイン側も Next.js を採用しましたが、結果的に良かったなと感じています。 Next.js で作っておけば、めんどくさい router の設定やデザイナーが苦手な webpack の config を記述しなくてすみます。 また、 next build && next export で静的な HTML ファイルとして書き出されるため、サーバがあればすぐに共有が可能です。今回はエンジニアさんに、develop ブランチに merge されると、 next build && next export が走り、自動で Amazon S3 に静的ファイルをデプロイされるようにしてもらいました。 この時点でプロダクト側のフロントエンド設計も進んでいたため、ESLint やコンポーネント設計、ライブラリなどを流用し、デザインプロジェクト用に最適化させます。 4.Next.js の設計 実際にエンジニアがプロダクトを実装する際には色々なことを検討する必要があると思いますが、デザインツールとして使用する際には、逆にそこまでガチガチにしてしまうと実装に工数がかかりすぎてしまうので「割り切り」が必要になります。私が実装した際の環境は以下のようなものです。 TypeScript は入れない。要件が固まりきっていない状態で型定義をやり始めると修正に時間がかかりすぎるため。 非同期通信処理も入れない。データがほしければローカルに json ファイルを配置しておく。 デザイン側のソースコードの汚さはあまり気にしない。プロダクト版を作成するときにフロントエンドエンジニアがきれいに作り直してくれる。 コンポーネント設計を意識する。共通コンポーネントとして使用する汎用的なものは先に洗い出しておく。 テストコードは書かない。そこまでページ数が多くない上、上記のような割り切りをしているので複雑性も極端に上がらない。 Google Chrome 最新版のみ対応とする。他のブラウザは無視する。 (昨今のフロントエンド開発の流れと真逆、、、) 5.デザインルール設計 続いてデザインルールの設計を行います。 theme.js ファイルを作成し、以下を定義します。この時点で定義が完全にできていることは無いと思うので、分かる範囲で書いていきます。最終的に、不要なものを消したり、一緒にできるものは統合して定義を減らしていきます。 各コンポーネントで padding や margin の余白を数値で指定したり、色味のカラーコドをベタ打ちせず、必ず theme ファイルから値を引っ張ってくるようにします。そうすると、修正が容易になる上、あとからどこで何が使われているかを把握しやすくなります。 ■theme 内に記述する内容のイメージ fontFamily// fontFamily を定義 colors// カラーコードの一覧 spaces // 4/8/16 など余白に使う数字を定義。 fontSizes // fontSize を定義 lineHeight // lineHeight を定義 fontWeight // fontWeight を定義。 boxShadow // ドロップシャドウを使用するなら定義 6.コンポーネント設計 続いて、コンポーネントとコンポーネントに必要な props を洗い出します。 世の中には優秀な UI フレームワークが複数存在していますのでそういったものを参考にします。そういったものはほとんど同じようなコンポーネント設計になっているのでコンポーネントの分け方や受け取る props などを参考にすると作業が捗ります。 Ant Design https://ant.design/ Material-UI https://material-ui.com/ Element https://element.eleme.io/#/en-US ここで気をつけたいのは、コンポーネントの数を極力減らすように努力することです。 同一機能の別コンポーネントが複数できてしまうと、今後の機能拡張時に、どのコンポーネントを使うか迷うことになります。ほとんどのエンジニアやデザイナーにとって、コンポーネント選びで迷うことは時間の無駄です。選択肢は極力減らす努力をし、減らせないようなら使用する場所を明確に定義する必要があります。 例えば component/tab1/ component/tab2/ component/tab3/ のようにタブコンポーネントが複数あると、あとから見たときにどれを使えばいいかわからなくなりますよね。 これを許容してしまうと、知らぬ間に component/tab4/ ができあがっていることでしょう。 7.実装 まずは大枠のページテンプレートを制作します。その後、小さいコンポーネントから順に作り上げていき、ページテンプレートに配置していきます。コンポーネント化ができていれば、見た目の変更はあとから行えるので、まずは page 内に配置し、機能することを目指します。 この時点で、デザインを細部まで作り込んだとしても、結局全体を見渡してから細かく調整をかけていくと思うので、そこまでセンシティブにならずに行っていきます。 8.確認・ヒアリング・修正の繰り返し 見た目が完全にできていない状態で、確認観点を絞って、PM や、ディレクター、実際に業務で使う方々にチェックしてもらいフィードバックを受けます。 徐々にブラッシュアップしていき、完成を目指します。 デザイン中には常に以下を意識して作業することで、無駄なものを介在させない設計を目指します。 コンポーネントを共通化できないか 色数を減らせないか fontSize や lineheight などの定義を減らせないか 9.各種資料の作成 作っているデザインではエラー処理などすべてを表現しきれないので、補足資料として別途スプレッドシートなどにまとめていきます。 また、実際のコンポーネントと想定している props、実装時の注意事項などを記載した UI コンポーネント集ページを制作し、フロントエンドエンジニアと共有します。 Storybook での共有も検討しましたが、受け渡す props の想定、エンジニアへの指示、要件の補足を記載していくだけですので、Storybook ほどの機能は不要と考え、Next.js 内にシンプルな Page を作り、そこに記述する方法を選択しました。 また、デザインの設計ルールも資料化し、最終的には各種資料と、制作したコード、S3 にアップされている URL を成果物としてエンジニアに実装をしていってもらいデザインのフェーズを完了させます。 React でデザインした場合のメリット 忠実度の高いモックアップが制作できる プロトタイプツールは数多くあれど、実装にまさる忠実度の高さなし。 最近は Figma の AutoLayout や XD のスタックなど、便利な機能も登場してきていますし、プロトタイピングに関しても様々なアクションが設定できるので、非常に便利になってきました。ただ、それでも CSS や JS の表現力にはまだ届かない部分も多いかなと感じています。 ボタンを押したとき、特定の <select/> の <option/> が選択されたとき、複数条件下でのみ表示させるもの、ウインドウサイズが小さくなったときの表示など、デザインツールで実装するにはやや面倒な箇所も、コードベースなら対応可能で、デザインファイルと実装されたページでの印象差も起こりづらいです。 実際に操作できる環境を渡すことで高い精度のフィードバックをもらえる 様々なリテラシーのユーザーが使用するサービスであるからこそ、よりリアルなプロトタイプを使用し、ミスコミュニケーションを減らせました。 結果論ですが、新型コロナウィルスによって、コミュニケーションを取りにくい状況が続きましたが、挙動を忠実に再現しているので、精度の高い意見を聞けたのは良かったです。 プロダクト版のフロントエンドの実装時に、こちらの意図が伝わりやすい fontSize や space、color を theme.js ファイルにまとめておき、そこからコンポーネント側では theme 側から読み込むようにしておけば、デザインルールが把握しやすくなります。また、CSS がすでに記述されているので、プロダクト版への移植も可能となり、「デザインファイルと実装でデザインが違う」が起こりにくくなります。 Git やエディタの恩恵をフルに受けられる 一旦別ブランチでデザイン案を作る、作ったブランチの commit から cherry-pick する、過去の log を見る、特定の commit に戻るなど、Git の恩恵をフルに受けられます。また、文字列の一括検索や置換が可能なので、色味を一気に置き換えたい、どこで使われているかを探したい場合などかなり重宝しました。 とはいえいいことばかりではなかった。。。 ちょっと要素の位置を変える、などはデザインファイルのほうが全然楽。コードベースだと CSS と HTML 構造自体を書き換えないといけない React を理解していないと、動かなくなったりした時に、修正で時間を余計に使ってしまう 他のデザイナーに引き継ぎしずらい など、通常のデザインファイルでは起こらないようなデメリットもありました。 結局の所プロジェクトによって向き不向きはあります。 個人的には社内の管理システム系のように、一般的なコンポーネントを組み合わせて、色々なデータを表示する必要があるサイト制作に向いているかなと思います。 逆に、特殊なコンポーネントを量産するケースや、LP のようにグラフィック要素が多くなってくるとデザインツールのほうがはかどります。 プロジェクトの性格に応じて最適なデザイン方法を選んでいきたいですね。 デザイナーだけどコードも書きたい方や、一緒にプルリク送ってくれるデザイナーの方いらっしゃれば、ぜひメドレーで一緒に働きましょう〜 募集の一覧 | 株式会社メドレー メドレーの採用情報はこちらからご確認ください。 www.medley.jp