プログラミング初心者の勉強ブログ #118
Firebaseを使って簡易的なチャットアプリを作成したのでまとめる。リアルタイム更新はもちろん、DBもストレージもあって、APIも少ない手間で実装できるしFirebaseすげーって感じでした。
目次
Firebase
G'sでそのうち習うっぽいが、早めにやっておこうと思いリアルタイム更新されるチャットアプリ的な物を作ってみることにした。
Firebaseで作成したもの
とりあえず動くが、何箇所か意図せず起こる挙動がまだあるので、下に載せているコードは参考程度。
Firebaseを使うと、JSでリアルタイムな画面表示を更新できるようなものを作成できる。Oauthによるログインも少ないコードで実装が可能。ちょっとしたアプリなら無料枠内でリリースとかできるんじゃないかって思う。機能多くてまだあまりよくわかってないが、Railsよりは少なくとも実装が簡単だった。小規模なものであればRails使わないでFirebase使った方が良さげなのかもしれん。Oauth実装とかもだいぶ楽。
Firebase Notificationsをやめた4つの理由 - Qiita
それでもFirebaseを使うべき5つのメリット - Qiita
Qiitaをいろいろと読んでみたもののあまり理解することができなかった。
Firebaseでバックエンドエンジニア不在のアプリ開発 クックパッドが体感した、メリットと課題 - エンジニアHub|若手Webエンジニアのキャリアを考える!
この記事が一番参考になった。というより面白かった。
コード
結構いろいろと調べた。Firebaseの仕様が高頻度で変わっているからなのかもしれないが、調べても過去の情報とかが多く、今これで書いても反映されないわ、って何回もなった。
公式のガイドが一番確実な情報を載っけてくれているが、とても探しづらかった。YouTube APIとかのリファレンスの方がよっぽど探しやすかった気がする。先にも書いたが、とりあえず動くが何箇所か意図していない挙動がある。コンソールで「firebase.INTERNAL.registerAppHook is not a function」と言う、なんかよくわからないエラーもまだ出てくる。
main.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
const init = function() { setConfig(); setLoginBtn(); setUser(); }; // firebaseの初期設定 const setConfig = function() { const firebaseConfig = { apiKey: "xxxxxxxxxxxxxxxxxxxx", authDomain: "xxxxx.firebaseapp.com", databaseURL: "https://xxxxx.firebaseio.com", projectId: "xxxxx", storageBucket: "xxxxx.appspot.com", messagingSenderId: "xxxxxxxx", appId: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }; firebase.initializeApp(firebaseConfig); }; // ログインボタンのイベント const setLoginBtn = function() { $('#loginBtn').on('click', function() { // この2行が大事。Twitter Oauthログイン画面にリダイレクトされる const provider = new firebase.auth.TwitterAuthProvider(); firebase.auth().signInWithRedirect(provider); setPreloader(); setUser(); }); }; // ユーザー情報取得 const setUser = function() { // onAuthStateChanged() でユーザーのログイン状態を判別できる firebase.auth().onAuthStateChanged(function(user) { this.user = user; if (this.user) { // ユーザーがログインしているとき setPreloader(); $('.logoutView').addClass('hide'); $('.loginView').addClass('show'); $('#username').html(this.user.displayName); setRef(); setLogoutBtn(); setSendBtn(); renderIdeas(); } else { // ユーザーがログインしていないとき $('#loginBtn').css('display', 'block'); } }); }; // firebase.database().ref()でfirebaseのDBを参照できる const setRef = function() { this.ideasRef = firebase.database().ref(); }; // ログアウトボタンのイベント const setLogoutBtn = function() { $('#logoutBtn').on('click', () => { // サインアウト firebase.auth().signOut(); $('.logoutView').removeClass('hide'); $('.loginView').removeClass('show'); }); }; // 送信ボタンのイベント const setSendBtn = function() { $('#send').on('click', () => { // pushでDBに値を保存 this.ideasRef.push({ // firebase.auth().currentUser.displayNameでログインユーザーのTwitterアカウント名取得 userName: firebase.auth().currentUser.displayName, title: $('#title').val(), text: $('#text').val(), }); $('#title').val(""); $('#text').val(""); }); }; // 投稿のレンダリング const renderIdeas = function() { // .on('child_added', {})でDB内全てのデータを選択 this.ideasRef.on('child_added', function(data) { const v = data.val(); const k = data.key; const idea = `<div class="idea" id='${k}'><div class="title">${v.title}</div><div class="user">${v.userName}</div><div class="content">${v.text}</div></div>`; $('#output').prepend(idea); removePreloader(); }); } // ローダー const setPreloader = function() { $('#preloaderBg').css('z-index', '1'); $('#preloaderBg').show(); $('#preloader').show(); }; const removePreloader = function() { $('#preloaderBg').fadeOut(800); $('#preloader').fadeOut(300); setTimeout(() => { $('#preloaderBg').css('z-index', '-1'); }, 800); } $(() => { init(); }); $(window).on('load', () => { removePreloader(); }); |
index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>stockidea</title> <link href="https://fonts.googleapis.com/css?family=Noto+Sans+JP" rel="stylesheet"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous"> <link rel="stylesheet" href="./css/style.css"> </head> <body> <!-- preloader --> <div id="preloaderBg"> <div id="preloader"> <img src="./img/preloader.gif"> </div> </div> <!-- /preloader --> <div class="container flex centering"> <!-- ログイン前 --> <div class="logoutView flex centering"> <h1 class="title">stockidea</h1> <div class="btn" id="loginBtn"><span><i class="fab fa-twitter"></i> Login</span></div> </div> <!-- /ログイン前 --> <!-- ログイン後 --> <div class="loginView borderBox"> <header class="header flex"> <div class="title">stockidea</div> <div id="username"></div> <div class="btn" id="logoutBtn"><span>Logout</span></div> </header> <div class="content borderBox"> <div class="input borderBox"> <input id="title" type="text" placeholder="Title"> <textarea id="text" rows="5" placeholder="Content"></textarea> <button id="send">Post</button> </div> <div id="output" class="flex borderBox"></div> </div> </div> <!-- /ログイン後 --> </div> <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> // firebase-app.jsは必ず必要 <script src="https://www.gstatic.com/firebasejs/5.11.1/firebase-app.js"></script> // firebase-auth.jsはログイン機能実装の場合必要 <script src="https://www.gstatic.com/firebasejs/3.1.0/firebase-auth.js"></script> // firebase-database.jsはDB使うなら必要 <script src="https://www.gstatic.com/firebasejs/3.1.0/firebase-database.js"></script> <script src="./js/main.js"></script> </body> </html> |
まとめ
JSだけで実装できるのが楽しい。バックエンドやった感覚は少ない。データ構造をもう少し複雑にして、また挑戦してみたい。
以上ありがとうございました。