LoginSignup
6
6

More than 3 years have passed since last update.

Fullstack React GraphQL TypeScript Tutorial をやってみた #1 ~MikroORMのセットアップまで~

Last updated at Posted at 2020-11-10

はじめに

30代未経験からエンジニアを目指して勉強中のYNと申します。
この記事はBen AwadさんのFullstack React GraphQL TypeScript Tutorialを初学者が進めていく、という内容です。
Benさんの動画は本当に質が高く、とても学びが多いのですが、自分のような初学者は躓きが多く、なかなか前に進まなかったので、振り返りのメモとして書きます。

今回の対象

動画の下記内容までです。
0:00:00 Intro
0:02:02 Node/TypeScript Setup
0:11:29 MikroORM Setup

始める前に

ローカルにコードをクローン

まずはBenさんのレポジトリを自分のgithubアカウントにFork。
そしてローカルにクローン。

git clone https://github.com/your-account-name/lireddit.git

ブランチをコピー

動画の内容ごとに細かくブランチを切ってくれています。ありがたや。
まずはブランチをローカルにコピーして、そのブランチに移ります。

git pull origin 1_mikroORM-setup:1_mikroORM-setup
git checkout 1_mikroORM-setup

Typescriptのはじめかた

tsconfig.jsonを作成

動画のこの部分です
ルートディレクトリで下記コマンドを実行してtsconfig.jsonを作成。コンパイルやデバックなどに関するtypescriptの設定ファイルを作成します。

npx tsconfig.json

tsc -wnodemon dist/index.jsを同時に実行する

動画のこの部分です
ts-nodeでtsファイルを実行するよりも、tscでtsファイルをコンパイルした後にjsファイルを実行した方が速いとのことです。

MikroORMの設定

データベースの作成

動画のこの部分です
この動画では PostgreSQLを使っています。ない人はインストールしましょう。
動画のように、createdb database-nameコマンドでデータベースを作成できますが、下記SQLコマンドでもできます。

psql 
# ログイン

CREATE DATABASE database-name;
# データベース作成

\l
# データベースの一覧を表示

DROP DATABASE database-name;
# データベースの削除

\q
# 退出

VScodeのオートコンプリートについて

動画のこの部分です
(自分のMac/JISキーボード環境では)cmd + . でオートコンプリートが使えます。

mikro-ORMの全体像について

動画のこの部分です
ORMとはObject-relational mapperのことで、面倒なSQL文を用いることなく、TypeScriptのみでデータベースとデータのやりとりをすることができます。

src/index.ts
const main = async () => {
  const orm = await MikroORM.init({
    dbname : 'lireddit',
    type : 'postgresql',
    entities : [Post]
  });
};

main()

上記のようにコードでMikroORMを初期化し、Postテーブルと情報をやりとりできるようになります。

スクリーンショット 2020-11-10 13.48.45.png

Entityについて

動画のこの部分です
Entityとはつまりテーブルのことです。
今回、TypeScriptのクラス構文とデコレータを使って下記テーブルのスキーマを定義します。
スクリーンショット 2020-11-10 13.57.29.png
(公式ドキュメントはこちら)

src/entities/Post.ts
import { Entity, PrimaryKey, Property } from "@mikro-orm/core";

@Entity() // クラスをテーブルスキーマに変換する
export class Post {
  @PrimaryKey() // idをプライマリキーのカラムとして定義する。SQLでインサートする際にはオートインクリメントしてくれる。
  id!: number // プライマリキーなので!をつける。nullを許さない。

  @Property({ type: "date" }) // createdAtをカラムとして定義する。SQLにDateという型はないので、date型を明示する。
  createdAt = new Date();

  @Property({ type: "date", onUpdate: () => new Date() }) // 同上。updateの度に新しい日付で上書きするhookを書き足す。
  updatedAt = new Date();

  @Property({ type: "text" }) // 同上。SQLにstringという型はないので、SQLではtext型を使うことを明示的に示す。
  title!: string;
}

まずもって最初に@~~とかいう見慣れない構文が唐突に出てきて困惑します。(しました。)
これがデコレータです。
デコレータはTypeScriptに導入された新しい構文で、近いうちにJavaScriptにも実装されるみたいです。
デコレータの機能を使うには、tsconfig.jsonに下記の設定を付け加える必要があります。

tsconfig.json
{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,  
  },
}

@Entity()はクラスを修飾するクラスデコレータ、@PrimaeryKey()はプロパティを修飾するプロパティデコレータです。
このデコレータを使うことによって、TypeScriptのclassをSQLのスキーマに翻訳できる魔法のようなものと捉えればいいと思います。
実際にどうやって翻訳するかが気になるひとはこちらに中身が書いてありますが、中身を意識せずありがたく使わせていただきましょう。
自分としては、

  • クラスデコレータはクラスを引数として受け取って、編集したクラスを返す関数
  • プロパティデコレータはプロパティを引数として受け取って、何かをする関数
  • デコレータを作るためには、決まった引数と決まったやり方がある

ぐらいを抑えておけば十分かなと思いました。
(自分はUdemyでデコレータについて勉強しましたが、デコレータを「使う」分には「便利だな」ぐらいに捉えておけばよいと感じました。)

Postテーブルを作成する

動画のこの部分です

1) mikro-orm.config.tsを作成

動画のこの部分です

src/mikro-orm.config.ts
export default {
  ...
} as Parameters<typeof MikroORM.init>[0];

ここでの一番の学びは、最後のas Parameters<typeof MikroORM.init>[0]です。
Parameters<>を付け加えることで、オブジェクトからMikroORMの初期化に関する引数以外を排除することができます。

2) migrationの設定

動画のこの部分です

migrationプロパティに、テーブルを作成するためのmigrationファイルを保存/実行する場所を設定します。

src/mikro-orm.config.ts
export default {
  migrations: {
    path: path.join(__dirname, "./migrations"),
    pattern: /^[\w-]+\d+\.[tj]s$/,
  },
  ...
} as Parameters<typeof MikroORM.init>[0];

3) migrationファイルの作成

動画のこの部分です
mikro-orm.config.tsに記載されたmigrationファイルを実行します。

npx mikro-orm migration:create

これにより、Entityプロパティに記載されているテーブルでまだ作成されていないものを自動的に検知し、(今回はPostテーブル)、Post.tsに記述されたスキーマに従ってテーブルを作成します。

4) migrationファイルの実行

動画のこの部分です

src/index.ts
const main = async () => {
  const orm = await MikroORM.init(microConfig);
  await orm.getMigrator().up(); // 先ほど作成したmigrationファイルを実行する
};

main()

ちなみに、orm.getMigrator().up()の部分で、一度実行されたmigrationファイルは裏で履歴をカウントされており、main()が再度実行されても、同じmigrationが再度実行されることはありません。動画のここにて言及されています。

Postテーブルにデータをinsertする

動画のこの部分です

src/index.ts
const main = async () => {
  const orm = await MikroORM.init(microConfig);
  const post = orm.em.create(Post, { title: "my first post" }); 
  // SQLのcreate tableとinsertを実行する。Postテーブルのスキーマに記載の通り、入力が必要なカラムはtitleだけであることに注意。
  // https://mikro-orm.io/docs/entity-manager-api#createentityname-entitynamet-data-entitydatat-newt-p
  await orm.em.persistAndFlush(post);
  const posts = await orm.em.find(Post, {});
  // 空オブジェクトを第二引数とすると、テーブル内のすべての行が帰ってくる
};

main()

persistAndFlushの使い方はこちらを参照。
Mikro-ORMによるSQL文の実行についてはこちらを参照。

最後に

今回はMikroORMの設定まで書きました。
チュートリアル全14時間のうち、40分ぐらい進みました。
先は長い。。。

次回=>https://qiita.com/theFirstPenguin/items/5ce4ca5b424b4fb4d9ef

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6