Firebaseっていう便利なやつ

f:id:utouto97:20211223102910p:plain

Firebaseって聞いたことはありますか?
ウェブアプリを開発するのに非常に役立つサービスが勢揃いのクラウドサービスです。

Firebaseとは

Firebaseとは、Googleが提供するBaaS (Backend as a Service) で、 Webアプリやスマホアプリの開発プラットフォームです。

Ruby on Rails 等のフレームワークを使って開発されることの多いバックエンドを、Firebaseを使うことで容易に構築することができます。
プログラムを書く必要もなく、Firebaseコンソールでポチポチとしていくだけです。
(権限の設定等、少々複雑なところもあります)

DBとDBアクセス、認証、ビジネスロジックを実行するサービス等、バックエンドとして必要な様々なサービスが、Firebaseでは提供されています。

これらを組み合わせて、アプリを構築することは当然できます。
それだけではなく、Rails等で構築した独自のバックエンドに、DBサービスや認証のサービスのみを組み込んで利用することも可能です。

要は、Railsとかをつかって開発してたバックエンドを代替するものを構築することができます。
そこまで複雑ではない処理を実行する程度であれば、Firebaseで十分実装可能で、コストを抑えることも可能になります。
初めて使う場合、学習コストが少々かかりますが、豊富なドキュメントがあり、Firebaseコンソールもわかりやすいので、結構簡単に使えてしまいます。
特に、開発・メンテが大変な認証をFirebaseに丸投げできるのは、非常に助かります。

Firebaseが提供するサービス

先にも述べましたが、FirebaseはDBや認証等様々なサービスが提供されています。

次にいくつか例を挙げます。

  • Firebase Hosting
    ホスティングサービス、ReactやVueもホスティング可能
  • Cloud Firestore
    ドキュメント型のNoSQL
  • Realtime Database NoSQL データベース
  • Authentication
    認証、トークンを利用
  • Cloud Functions
    アプリのロジックを実行
  • Cloud Storage
    ストレージ
  • Firebase ML
    機械学習

その他、アナリティクスやモニターなどのアプリケーションを監視できるようなサービスも提供されています。

Cloud Firestore と Realtime Database
Firebaseの公式ページには次のように書かれています。

  • Cloud Firestore は、Firebase のモバイルアプリ開発用の最新データベースです。直感的な新しいデータモデルで Realtime Database をさらに強化しています。Cloud Firestore は、Realtime Database よりも多彩で高速なクエリと高性能なスケーリングが特長です。
  • Realtime Database は従来からある Firebase のデータベースです。リアルタイムのクライアント間同期が必要なモバイルアプリのための、効率的でレイテンシが低いソリューションです。

基本的には、Cloud Firestoreを利用し、より速度が重要な場面ではRealtime Databaseを利用すればよさそうです。

サービス一覧については↓の辺を見に行けばすべて書かれています。

firebase.google.com

また、それぞれの使い方も豊富なドキュメントにより説明されています。

firebase.google.com

数多くあるサービスのすべてを使う必要がなく、DBだけ、認証サービスだけのように必要なものだけを利用することもできます。
簡単に始められるので一度試してみるのはいかがでしょうか。

TypeScript きほんの「き」

f:id:utouto97:20210706233746p:plain

TypeScript きほんの「き」
TypeScriptを書く上でとりあえずこれを知っておけばいいというのをまとめてみました。

変数に型をつける

TypeScriptは、JavaScript + 型 みたいなものです。

utouto97.hatenablog.com

ですので、JavaScriptのプログラムに型をつけていきましょう。

まずは、変数からみていきます。

変数には、その変数の宣言時に型をつけることができます。
その方法は非常に簡単で、変数名の後ろに : を挟んで型名を書くだけです。

const msg : string = "Hello!";

ここで使える型名には次のようなものがあります。

  • boolean
  • number
  • string
  • any
  • Array<T> または T[] (Tは型名)
  • 自分で宣言した型
  • 関数型

変数の型と代入する値の型が異なるとエラーとなります。

const msg : string = 1; // 1はnumber

上記のプログラムを実行すると、 Type 'number' is not assignable to type 'string'.というエラーが発生します。
これは、string型の変数に、number型の値(1)を代入しようとしているからです。

any型

any型はどんな型でもOKな型です。
つまり、any型の変数には、number型の値でも、string型の値でも、 自分で宣言した型の値でも代入することができます。

var msg : any = "Hello";
console.log(typeof msg); // string
msg = 123;
console.log(typeof msg); // number

typeofはその後ろに続く変数の型を取得することができます。
上の例をみてみると、2行目のtypeofではstring型、4行目のtypeofではnumberであるということがわかります。
変数宣言時には、anyを指定しているので、異なる型の値を後から代入してもエラーにはなりません。

型推論

TypeScriptでは、自明な型は自動で推論してくれます。

const msg = "Hello";
console.log(typeof msg); // string

string型である "Hello" で初期化をしているので、変数msgはstring型であると推論されています。
このように、初期化時に代入される値の型をその変数の型であると推論してくれます。

複数の型に対応

|でつなぐことで複数の型に対応させることができます。

var msg : string | number = "Hello";
console.log(typeof msg); // string
msg = 123;
console.log(typeof msg); // number

配列の型宣言

配列の型宣言はArray<T>を使います。
Tには配列の要素の型を入れます。

const a : Array<number> = [1, 1, 2, 3, 5, 8];

また、T[]という形式でも記述することができます。

const a : number[] = [1, 1, 2, 3, 5, 8];

自分で型を宣言する

自分で型を宣言する方法は2種類あります。
それはinterfaceを使う方法とtypeを使う方法です。

interfacetypeは別物であり、それぞれ特徴がありますが、基本的な使い方はどちらも同じです。

interface User {
  name: string;
  age: number;
}

type User {
  name: string;
  age: number;
};

interfacetypeで宣言された型は、stringやnumberと同様に使えます。

interface Pos {
    x: number;
    y: number;
}

const p : Pos = {
    x : 100,
    y : 200
}

TypeScriptってなんやねん

f:id:utouto97:20210725220659j:plain

TL;DR
TypeScriptは静的型付けなJavaScriptで、保守性向上に貢献

TypeScriptとは

TypeScriptとはなんでしょうか。

とりあえず、Wikipediaを見てみましょう。

TypeScript はマイクロソフトによって開発され、メンテナンスされているフリーでオープンソースプログラミング言語である。TypeScriptはJavaScriptに対して、省略も可能な静的型付けとクラスベースオブジェクト指向を加えた厳密なスーパーセットとなっている。
TypeScript - Wikipedia

TypeScriptとはプログラミング言語です。
Wikipediaを見る限り次のような特徴があります。

つまり、TypeScriptは静的型付けとオブジェクト指向を取り入れたJavaScriptの拡張だということです。

続いて、公式HPを見てみましょう。

www.typescriptlang.org

次のように、書かれています。

f:id:utouto97:20211203015052p:plain

"TypeScript is JavaScript with syntax for types."

"TypeScriptは、型構文をもつJavaScriptである."

ということで、やっぱりTypeScriptはJavaScriptに型を追加したものであることがわかります。

TypeScriptはオープンソースです。
GitHubリポジトリがあります。

github.com

使われている言語を見てみると、TypeScript 100%となっており、TypeScript自体がTypeScriptで書かれていることが確認できます。

f:id:utouto97:20211203015553p:plain

TypeScriptはコンパイラ!?

TypeScriptは型構文をもつJavaScriptであるということはわかりました。
では、TypeScriptはどのように実行するのでしょうか。
JavaScriptの場合は、ブラウザやNode.jsが実行します。
それは、各ブラウザはJavaScriptを実行できるようになっているからです。
(バージョンの話とかありますが割愛)

TypeScriptの実装は、TypeScriptからJavaScriptへのコンパイラとなっています。
つまり、TypeScriptで書かれたプログラムは、コンパイルされてJavaScriptへと変換されます。
そして、変換されたJavaScriptがブラウザやNode.jsで実行されます。

TypeScriptコンパイラはそのコンパイル時に、型チェックやエラーチェックを行います。
これにより、明らかなエラーを先に見つけることができます。
例えば、JavaScriptの場合、実行時にエラーとなるため、次のようなエラーが続発することがあります。

Uncaught TypeError: Cannot read property *** of undefined

TypeScriptを利用している場合、コンパイル時にこのようなエラーを見つけることができます。

どうしてTypeScriptが必要?

JavaScriptに変換されるのに、どうしてTypeScriptを使うのでしょうか。

主な理由は、保守性を高めることができるから、です。

TypeScriptは、静的型付け言語でコンパイル時に、型チェック・エラーチェックが行われます。
先に述べたUncaught TypeError: Cannot read property *** of undefinedのようなエラーもコンパイル時にわかります。
これにより保守性を高めることができます。

また、コードを読むときにも、型が分かっているほうが読みやすいです。
動的型付けだと、実行時にコンピュータが自動で型を判断してくれます。
ただし、コーディングしてるときは、エンジニアが脳内で型を判断しながらコードを読む必要があります。
そのため、静的型付けで型がはっきりと書かれているとコードが読みやすくなります。

ほかにも、TypeScriptを使っていると、VSCodeなどのエディタの入力補完が協力になります。
JavaScriptを書いているときよりも、TypeScriptを書いているほうが強力な入力補完を使うことができ、タイポを減らしたり、楽にコーディングが可能になります。

はじめに一度だけ実行したい

f:id:utouto97:20210704222351j:plain

Composition APIを使って開発をするとき、はじめの一度だけ実行したい処理の記述方法をまとめていきます。

マウント直後に実行する

はじめの一度だけ実行したい場合、DOMが作成されマウントされた直後に、処理を実行することで、はじめの一度だけ実行できます。
そして、Composition API では、onMountedを利用することで、マウント直後に実行する処理を記述することができます。

onMountedは、Compostion APIsetup()内に記述します。
そして、onMountedには、実行したい関数を渡すことで、マウント直後に実行したい処理を記述します。

export default {
  setup() {
    onMounted(() => {
      console.log('Component is mounted!')
    })
  }
}

Composition API では、マウント直後(onMounted)のように、あるタイミングで実行したい処理を記述する方法が提供されています。

ライフサイクルフック

Vueコンポーネントに、「あるタイミング」で処理を実行したい場合があると思います。
例えば、マウント直後、マウント前、再レンダリング前、再レンダリング後、破棄されたとき、などのタイミングで処理を実行できるようなものが用意されています。

これらをライフサイクルフックと呼びます。
Composition API では、例に挙げたライフサイクルフックが提供されています。

ライフサイクルフック タイミング
onMounted マウント直後
onBeforeMount マウント前
onBeforeUpdate レンダリング
onUpdated レンダリング
onUnmounted 破棄されたとき

このほかにも、ライフサイクルフックがいくつか提供されています。
詳しくは、↓にかかれています。

v3.ja.vuejs.org

これらのライフサイクルフックは、onMountedと同様に、setup()内に記述し、そのタイミングで実行したい関数を引数として渡します。

ライフサイクルフックを利用することで、ある特定のタイミングで処理が実行できます。

Composition API ってどうやって使うの?

f:id:utouto97:20210706233740j:plain

Vue 3 でComposition API が追加され、ロジック毎にまとめて記述できるようになりました。
そんな Composition API の基本的な使い方をまとめていきます。

HTML は <template>タグ内に記述

まずは、HTMLの記述ですが、これはVue 2の時と変わらず、テンプレートを使用することができます。

<template></template>内に、HTMLをほぼ通常通り記述することができます。
Reactのように、JSX記法を新たに覚える必要はありません。
一般的なHTMLと、記述が異なる点もありますが、大きな違いはないので、HTMLが記述できれば、<template>タグ内にそのまま記述していくだけです。

<template>
  <div>
    <h1>Composition API を使ってみた</h1>
  </div>
</template>

変数や関数を使う

では、JavaScriptで変数や関数を宣言し、<template>タグ内で使っていきましょう。

Composition API では、変数や関数は setup() で宣言をします。
そして、<template>タグ内で使用する変数や関数はreturnしておく必要があります。

<script>
import { ref } from "vue";

export default {
  const count = ref(0);

  const countUp= () => {
    count.value++;
  };
  
  return {
    count,
    countUp
  }
}
</script>

ここで、変数の宣言を見ていると、const count = ref(0);となっています。
これは変数を「リアクティブ」にしています。

リアクティブな変数とは、値の変更が検知され、HTMLタグ内で使用されている部分が自動で更新される変数となります。
つまり、リアクティブな変数の値が変更されると、HTMLで表示される値も自動で変更されます。

Composition API で、リアクティブな変数を宣言するには、refreactiveを使うことができます。
詳細は、↓を参照してください。

v3.ja.vuejs.org

setup()returnした変数や関数は、<template>タグ内で使用可能です。
変数の値を表示するには、{{ }}を使います。
一般のHTMLと異なる点として、「クリックされた時」は、onClickではなく、@clickを使用します。

<template>
  <div>
    <h1>Composition API を使ってみた</h1>
    <div>{{ count }}</div>
    <button @click="countUp">+1</button>
  </div>
</template>

ここまでで、HTMLで要素を記述し、変数や関数も利用できるようになりました。
Composition API の基本的な使い方はできるようになったと思います。

また、<template>タグ内では、idclass、またstyleも指定することもでき、CSSをいつも通り記述できます。
多くのCSSフレームワークも利用可能です。

Vue 2 と Vue 3

f:id:utouto97:20210725220659j:plain

Vue はバージョン3がリリースされていますが、Vue 2 もまだまだ使われているようです。
Vue CLI でプロジェクト作成時も、Vue のバージョンを2にするか3にするか、問われます。
Vue のバージョン3でどんな機能が追加されたのでしょうか。

バージョン3での変更点

Vueはバージョン2からバージョン3へのアップデートにより、新機能の追加、破壊的な変更がいくつも行われています。
注目すべき新機能の中に、Composition API や Teleport などがあります。
また、Global API も破壊的な変更が行われているため、Vue 2からVue 3への移行時は注意が必要です。

すべての変更点の詳細については、以下の公式ドキュメントに記載されています。

Composition API

Vue 2 では、Option API を用いてコンポーネントを作成していました。
Vue 3 では、Composition API が追加されました。

Option API では、ライフサイクル毎に、処理を記述していきます。
この場合だと、ロジックの各処理がソースコード内で分散することになります。
そうなると、コンポーネントが大規模になると、可読性が低くなってしまいます。

そこで、Composition API です。
Composition API では、ロジック毎に処理を記述していきます。
例えば、APIを叩くロジック、LocalStorageからデータを読み込むロジック、などそれぞれのロジック毎に、処理をまとめて記述することが可能になります。
こうすることで、ロジック毎に処理がまとまり、可読性が向上します。

PRにある↓の画像がイメージしやすいです。

f:id:utouto97:20211108010953p:plain https://github.com/vuejs/rfcs/pull/42

各色はそれぞれのロジックを示しています。
Vue 2 の Option API では、ライフサイクル毎に処理をまとめて記述するため、ロジック毎にみると、コードはバラバラになってしまいます。
一方で、Vue 3 の Composition API では、ロジック毎にまとめて記述できるので、図の右のようになります。

Teleport

Vue 3にはTeleportという機能もあります。
Vue 2でも、Portal Vue というプラグインを利用すれば、類似の機能が使えたようです。
https://github.com/LinusBorg/portal-vue

Teleport とは、その名前のイメージ通り、コンポーネントを別の場所に移動できます。
↓のサンプルを見たほうがイメージしやすいと思います。

<teleport to="#modals">
  <div>A</div>
</teleport>

<div id="modals">
</div>

このように記述することで、内の要素が、teleport to の先に移動されます。
上のサンプルの場合だと、<div id="modals"></div>の中に、<div>A</div>が移動されます。
結果として次のようになります。

<div id="modals">
  <div>A</div>
</div>

Vue Router

f:id:utouto97:20210706233746p:plain

Vue Router

Vueでは、シングルページアプリケーション (SPA) をつくることができます。
SPAでは、ページは1枚だけです。
しかし、URLをもとに複数の画面を表示したいときもあります。
そんなときに、Vue Router を使ってルーティングを行います。

router.vuejs.org

Vue Router は、VueにおけるSPAで、ルーティングを制御するためのプラグインです。
Vue Routerを使うことで、SPAに複数ページを疑似的に実現することができます。

Vue Routerのインストールは、Vue CLI を使って簡単にできます。
一つは、vue createでプロジェクトを作成するときに、Vue Routerを選択し、追加することができます。
別の方法として、vue add vue-routerとすることでインストールすることができます。

Vue Routerでは、Routerクラスのインスタンスをつくり、Vue app本体に追加することで利用できます。

Routerクラスのインスタンス作成時には、routesを渡すのですが、その中でルーティングの設定を行います。

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      component: About
    }
  ]
})

終わり