Slide 1

Slide 1 text

Firebase for Web 2019/06/19 GCPUG Kobe #6 rito

Slide 2

Slide 2 text

Agenda ❏ 自己紹介 ❏ Webアプリケーションに必要なインフラ達 ❏ Firebaseの特徴 ❏ Webアプリケーションを支えるFirebaseの機能 ❏ Authentication ❏ Cloud Firestore ❏ Cloud Storage ❏ Hosting ❏ Cloud Messaging ❏ まとめ 2

Slide 3

Slide 3 text

自己紹介 名前: rito 職業: Webエンジニア (アプリケーションエンジニア) 分野: Ruby on Rails, Nodejs, React, Docker, AWS, GCP 所属: Ateam Finergy Inc. CTO コミュニティ: Rails follow-up Osaka Osaka Web Developers Meetup twitter: @chimame_rt GitHub: chimame 3

Slide 4

Slide 4 text

Webアプリケーションに 必要なインフラ達

Slide 5

Slide 5 text

ベーシック構成 5 Cloud Load Balancing Cloud Storage Cloud DNS Compute Engine Cloud Datastore Cloud SQL Cloud Memorystore Cloud Functions Web http Cloud CDN

Slide 6

Slide 6 text

1から全て構築した経験がある人は❓ 6

Slide 7

Slide 7 text

7 経験者でもそこそこ 面倒 時間がかかる

Slide 8

Slide 8 text

Webアプリケーションインフラ構築の課題 ❏ Webアプリケーション全体としてはフロントだけで はなく、バックエンドやインフラも必要 ❏ フロントからバックエンドまで全部管理するにはな かなか大変 ❏ 仮にWebアプリケーションをオンプレで構築する と… 8

Slide 9

Slide 9 text

9 主要PaaS

Slide 10

Slide 10 text

フロントからバックエンドまで 全部構築するのはなかなかしんどい 10

Slide 11

Slide 11 text

11

Slide 12

Slide 12 text

Firebaseの特徴

Slide 13

Slide 13 text

“ 13 Firebaseとは ◂ 2014年にGoogleが買収し、Google Cloud Platformの仲間入り ◂ FirebaseはmBaaS(mobile backend as a service)であり、名の通りモバイルアプリ ケーション向けのバックエンドサービス ◂ バックエンドサービスが高機能かつ多種存在

Slide 14

Slide 14 text

14 Cloud Load Balancing Cloud Storage Cloud DNS Compute Engine Cloud Datastore Cloud SQL Cloud Memorystore Cloud Functions Web http ベーシック構成 基本的な構成での カバー範囲はというと…

Slide 15

Slide 15 text

15 Cloud SQL Cloud Memorystore Web http ベーシック構成 Cloud Load Balancing Cloud Storage Cloud DNS Compute Engine Cloud Datastore Cloud Functions Cloud CDN

Slide 16

Slide 16 text

16 Cloud SQL Cloud Memorystore Web http ベーシック構成 Cloud Load Balancing Cloud Storage Cloud DNS Compute Engine Cloud Datastore Cloud Functions Cloud CDN Fireabaseが提供するバックエンド サービスでカバーできる範囲

Slide 17

Slide 17 text

17 Cloud SQL Cloud Memorystore Web http ベーシック構成 Cloud Load Balancing Cloud Storage Cloud DNS Compute Engine Cloud Datastore Cloud Functions Cloud CDN Google Cloud Next ‘19で発表されたCloud Runと連携することでカバー可能

Slide 18

Slide 18 text

Webアプリケーションを 支えるFirebaseの機能

Slide 19

Slide 19 text

19 Authentication

Slide 20

Slide 20 text

概要 ◂ その名の通り認証(ログイン)機能を提供 ◂ SNS認証はもちろんメール、電話番号とこのサー ビス1つで 様々な認証 に対応 ◂ この機能を使うだけでもFirebaseを使用するとい う価値有 20

Slide 21

Slide 21 text

21 Cloud Load Balancing Cloud Storage Cloud DNS Cloud Datastore Cloud SQL Cloud Memorystore Cloud Functions Web http Cloud CDN ベーシック構成 Compute Engine 各種SNS この部分を提供しているイメージ

Slide 22

Slide 22 text

実装例 22

Slide 23

Slide 23 text

クライアント 23 Hosting Firebase Authentication 各種SNS APIサーバ SNSログインボタン ID、パスワード入力 301 redirect ユーザおよびtoken作成 ログイン画面 token付きリクエスト token 検証 処理の流れ ユーザ(token)返却

Slide 24

Slide 24 text

クライアント 24 Hosting Firebase Authentication 各種SNS APIサーバ SNSログインボタン ID、パスワード入力 301 redirect ユーザおよびtoken作成 ユーザ(token)返却 ログイン画面 token付きリクエスト token 検証 処理の流れ

Slide 25

Slide 25 text

// GitHubアカウントでログイン const provider = new firebase.auth.GithubAuthProvider() const handleSignIn = async () => { try { await firebase.auth().signInWithPopup(provider) } catch (e) { console.log(e.message) } } SignIn 25

Slide 26

Slide 26 text

クライアント 26 Hosting Firebase Authentication 各種SNS APIサーバ SNSログインボタン ID、パスワード入力 301 redirect ユーザおよびtoken作成 ユーザ(token)返却 ログイン画面 token付きリクエスト token 検証 処理の流れ

Slide 27

Slide 27 text

let loginUser = null firebase.auth().onAuthStateChanged(user => { if (user) { // ログインされたユーザを保存 loginUser = user // token取得は以下 // loginUser.getIdTokenResult() } else { loginUser = null } }) 27

Slide 28

Slide 28 text

ログインだけならこれでOK 28

Slide 29

Slide 29 text

APIサーバも認証をかけたい 29

Slide 30

Slide 30 text

クライアント 30 Hosting Firebase Authentication 各種SNS APIサーバ SNSログインボタン ID、パスワード入力 301 redirect ユーザおよびtoken作成 ユーザ(token)返却 ログイン画面 token付きリクエスト token 検証 処理の流れ

Slide 31

Slide 31 text

// リクエストする毎にgetIdTokenResultする // なぜならtokenの有効期限はデフォルトで1時間のため、1時間毎に変わる fetch('https://example.com', { headers: { 'Authorization': `Bearer ${loginUser.getIdTokenResult()}` } }).then(function(response) { return response.json() }).then(function(json) { ... }) 31

Slide 32

Slide 32 text

クライアント 32 Hosting Firebase Authentication 各種SNS APIサーバ SNSログインボタン ID、パスワード入力 301 redirect ユーザおよびtoken作成 ユーザ(token)返却 ログイン画面 token付きリクエスト token 検証 処理の流れ

Slide 33

Slide 33 text

import * as admin from 'firebase-admin' // クライアントから送られてきた tokenを検証 admin.auth().verifyIdToken(token) .then(function(decodedToken) { var uid = decodedToken.uid; // ... }).catch(function(error) { // Handle error }) 33

Slide 34

Slide 34 text

Nodejs、Java、Python、Go、C#なら Firebase-adminのライブラリが提供されている それ以外の言語は自分で検証ロジックを 実装すれば可能で、仕様は以下を参照 https://firebase.google.com/docs/auth/ad min/verify-id-tokens?hl=ja#verify_id_tok ens_using_a_third-party_jwt_library 34

Slide 35

Slide 35 text

35 Cloud Firestore

Slide 36

Slide 36 text

概要 ◂ NoSQLデータベースを提供 ◂ クライアントのデータベースに書き込みを行うこと で、オンライン時に同期 (なのでオフラインでも動作可能) ◂ Webに対応しているのはCloud Firestoreのみ (Realtime Databaseは非対応) 36

Slide 37

Slide 37 text

37 Cloud Load Balancing Cloud Storage Cloud DNS Cloud SQL Cloud Memorystore Cloud Functions Web http Cloud CDN Compute Engine ベーシック構成 この部分を提供しているイメージ Cloud Datastore

Slide 38

Slide 38 text

38 Server Client

Slide 39

Slide 39 text

39 Server Client ローカルに書き込む要領で データを保存

Slide 40

Slide 40 text

40 Server Client オンライン時に自動的に サーバに保存

Slide 41

Slide 41 text

41 Server Client オンライン時に自動的に サーバからデータを取得

Slide 42

Slide 42 text

DEMO 42

Slide 43

Slide 43 text

const db = firebase.firestore() let writing = false const handleMouseMoveWriting = (e) => { if (!writing) { writing = true setTimeout(() => { db.collection("lines").add({ x: e.clientX, y: e.clientY }) }, 100) } } 43

Slide 44

Slide 44 text

// onSnapshotでデータの変更を監視 db.collection('lines').onSnapshot(doc => { doc.docs.forEach(d => { const div = document.createElement('div') const { x, y } = d.data() div.style.left = x div.style.top = y element.appendChild(div) }) }) 44

Slide 45

Slide 45 text

45 Cloud Storage

Slide 46

Slide 46 text

概要 ◂ その名の通りファイル保存サービス ◂ Authenticationと連携し、read(ダウンロード) とwrite(アップロード)を制御することが可能 46

Slide 47

Slide 47 text

47 Cloud Load Balancing Cloud SQL Cloud Memorystore Cloud Functions Web http Compute Engine Cloud Datastore Cloud DNS Cloud CDN ベーシック構成 この部分を提供しているイメージ Cloud Storage

Slide 48

Slide 48 text

48 Hosting

Slide 49

Slide 49 text

概要 ◂ 静的なWebサイトを公開することが可能 (SPA向き) ◂ 配信にはグローバルなCDNのエッジサーバから SSLにて配信 ◂ APIが必要な場合もCloud Runを用いて容易に 構築が可能 new 49

Slide 50

Slide 50 text

50 Cloud Load Balancing Cloud SQL Cloud Memorystore Cloud Functions Web http Compute Engine Cloud Datastore ベーシック構成 この部分を提供しているイメージ Cloud DNS Cloud CDN Cloud Storage

Slide 51

Slide 51 text

deploy方法 51

Slide 52

Slide 52 text

$ npm install -g firebase-tool $ firebase login $ firebase init $ firebase deploy 52

Slide 53

Slide 53 text

$ npm install -g firebase-tool $ firebase login $ firebase init $ firebase deploy 53 これで作成される firebase.json が大事

Slide 54

Slide 54 text

// firebase.json { "hosting": { "public": "build", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ], "rewrites": [ { "source": "**", "destination": "/index.html" } ] } } 54 create-react-appでの使用例

Slide 55

Slide 55 text

// firebase.json { "hosting": { "public": "build", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ], "rewrites": [ { "source": "**", "destination": "/index.html" } ] } } 55 どのディレクトリを対象とするか

Slide 56

Slide 56 text

// firebase.json { "hosting": { "public": "build", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ], "rewrites": [ { "source": "**", "destination": "/index.html" } ] } } 56 アップロード対象外とするファイル

Slide 57

Slide 57 text

// firebase.json { "hosting": { "public": "build", "ignore": [ "firebase.json", "**/.*", "**/node_modules/**" ], "rewrites": [ { "source": "**", "destination": "/index.html" } ] } } 57 特定ルーティング時の挙動 例はすべてのルーティングをindex.htmlへ react-router を使用していれば

Slide 58

Slide 58 text

rewrite定義を こんな感じに変更すると… 58

Slide 59

Slide 59 text

// firebase.json { "hosting": { ..., "rewrites": [ { "source": "/api/**", "run": { "serviceId": "cloud-run-name", "region": "us-central1" } }, { "source": "**", "destination": "/index.html" } ] } } 59 /apiのルーティングはCloud RunというGoogle Cloud PlatformにデプロイされたDockerコンテ ナにリクエストされる

Slide 60

Slide 60 text

60 Cloud SQL Cloud Memorystore Cloud Functions Cloud Datastore ベーシック構成 /apiはこっちのルートへ Cloud DNS Cloud CDN Cloud Storage Cloud Load Balancing Compute Engine Web http

Slide 61

Slide 61 text

61 Cloud SQL Cloud Memorystore Cloud Functions Cloud Datastore ベーシック構成 /api以外はこっちのルートへ Cloud DNS Cloud CDN Cloud Storage Cloud Load Balancing Compute Engine Web http

Slide 62

Slide 62 text

Cloud Runとの連携メリット ◂ 同一ドメインでのアクセスなのでAPIをクロスドメイ ンで受ける必要はなくなる ◂ 設定次第ではあるが /(ルート) 以外はCloud Runに流して、Nextjs/Nuxtjs等のSSR実施のた めのリクエストとするということも可能 62

Slide 63

Slide 63 text

Cloud Runとの連携デメリット ◂ GCP側のCloud Runを有効にするとFirebase のSparkプランからBlazeプランに自動的に変更 される 63

Slide 64

Slide 64 text

64 Cloud Messaging

Slide 65

Slide 65 text

概要 ◂ サーバからクライアントへデータを発信(PUSH通 知)するサービス ◂ PWAを用いて通知処理を実施 ◂ 発信(サーバ)と受信(クライント)には多少の実装 が必要 65

Slide 66

Slide 66 text

66 Cloud Load Balancing Cloud SQL Cloud Functions Web http Cloud Datastore Cloud DNS Cloud CDN Cloud Storage ベーシック構成 この部分を提供しているイメージ (RedisをPub/Subで使用) Cloud Memorystore Compute Engine

Slide 67

Slide 67 text

実装例 67

Slide 68

Slide 68 text

クライアント 68 Firebase Authentication APIサーバ token要求 tokenの通知 push通知 通知受信 処理の流れ push通知の許可 tokenの保存

Slide 69

Slide 69 text

クライアント 69 Firebase Authentication APIサーバ token要求 tokenの通知 push通知 通知受信 処理の流れ tokenの保存 push通知の許可

Slide 70

Slide 70 text

// ここはアプリケーション内の JavaScript const messaging = firebase.messaging() // push通知許可 await messaging.requestPermission() // ここは /firebase-messaging-sw.js を用意して記述しておく importScripts('https://www.gstatic.com/firebasejs/5.7.3/firebas e-app.js') importScripts('https://www.gstatic.com/firebasejs/5.7.3/firebas e-messaging.js') firebase.initializeApp({ 'messagingSenderId': 'your project messaging send id' }) const messaging = firebase.messaging() 70

Slide 71

Slide 71 text

クライアント 71 Firebase Authentication APIサーバ token要求 tokenの通知 push通知 通知受信 処理の流れ tokenの保存 push通知の許可

Slide 72

Slide 72 text

const messaging = firebase.messaging() // tokenを取得する const defaultToken = await messaging.getToken() // tokenは定期的に更新される messaging.onTokenRefresh(() => { messaging.getToken() .then((token) => { // サーバにtokenの変更を知らせる // fetch(‘http://example.com/answer’) }) .catch((err) => { console.error(err) }) }) 72

Slide 73

Slide 73 text

クライアント 73 Firebase Authentication APIサーバ token要求 tokenの通知 push通知 通知受信 処理の流れ tokenの保存 push通知の許可

Slide 74

Slide 74 text

74

Slide 75

Slide 75 text

クライアント 75 Firebase Authentication APIサーバ token要求 tokenの通知 push通知 通知受信 処理の流れ tokenの保存 push通知の許可

Slide 76

Slide 76 text

const messaging = firebase.messaging() // アプリケーションのJavaScriptにonMessageを書くパターン // これが呼ばれる条件は「該当の Webアプリ(のページ)がアクティブであるこ と」 messaging.onMessage((payload) => { console.log(payload) }) 76

Slide 77

Slide 77 text

// /firebase-messaging-sw.js にsetBackgroundMessageHandler を書くパ ターン // これが呼ばれる条件「該当の Webアプリ(のページ)がアクティブでないこと and サーバPUSHのデータに`notification`が存在しないこと」 messaging.setBackgroundMessageHandler ((payload) => { const notificationTitle = 'Background Message Title' const notificationOptions = { title: 'push-test-web', body: 'push-test-web: Background Message body' , icon: '/favicon.ico', } return self.registration.showNotification(notificationTitle, notificationOptions) }) 77

Slide 78

Slide 78 text

DEMO 78

Slide 79

Slide 79 text

ただ、こいつは若干クセがあります 79

Slide 80

Slide 80 text

【その1】 通知するためのサーバエンドポイントが 2種類ある 80

Slide 81

Slide 81 text

レガシーAPI: https://fcm.googleapis.com/fcm/send HTTP v1 API: https://fcm.googleapis.com/v1/projects/ /messages:send 81

Slide 82

Slide 82 text

【その2】 通知を受け取るパターンが 3パターンあり、1つは表示がプログラムで変 更できない 82

Slide 83

Slide 83 text

83 呼ばれるハンドラー条件 画面アクティブ notification有無 onMessage ○ - setBackgroundMessageHandler ☓ ☓ 非プログラミング ☓ ○

Slide 84

Slide 84 text

まとめ

Slide 85

Slide 85 text

まとめ ◂ Firebaseを使用することでバックエンド、特にイン フラ構築コストを削減することが可能 ◂ ネイティブアプリだけでなく、Webでも活用するこ とが可能 ◂ Google Cloud Platformと連携すれば更に便 利になる ◂ デモで使用したコードはこちら https://github.com/chimame/firebase-sample 85

Slide 86

Slide 86 text

86

Slide 87

Slide 87 text

87

Slide 88

Slide 88 text

88 Thanks! ご清聴ありがとうございました。 ◂ rito ◂ @chimame_rt