Hajimeの妄言とTechの部屋

このブログでは、テック系の話や、ドキュメントに関する話などをエンジニアが「こんな感じに使うとええんじゃね?」ということを書き連ねるブログです。

プロセカのNotionページ作って公開しました!!

第0章: はじめに

新年のご挨拶

皆様、新年あけましておめでとうございます。 mm
本年も皆様よろしくお願いいたします。

本記事に関して

本記事は3パートに分けています。
本記事のメイントピックはプロセカのページを作った話ですので、「Notion知ってる」って方や「プロセカ知ってる」っていう方は第1章、第2章はスキップして、「第3章: プロセカのNotionページ作って公開しました!!」に移動してしまってOKです。

プロセカ楽曲DBのGif
プロセカ楽曲DB

第1章: Notionとは?

Notionに関しては、去年のQiita Advent Calendar( Calendar for ABEJA | Advent Calendar 2021 - Qiita )のわたしの記事( 会社の公用ドキュメントツールをDocbaseからNotionに変更した件 - Qiita )に書いていることを踏襲します。

① マークダウンで記載可能

記載の際、マークダウンのように記載することで、そのフォーマットにあった表示を入力することが可能になります。 例えば、

- リスト表示
    - 1つ目のインデント
    - 2つ目のアイテム
    1. 数字リスト表示
    2. 2つ目の数字アイテム

のような入力をした場合、↓このようなフォーマットに整形されます。

② 様々な表現方法を実現

画像のように、ドキュメントの任意の場所に画像を挿入したり、リスト表示やCalloutによる強調表現、各種ウェブページ・ウェブサービスの埋め込み等が可能になっています。

https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F102773%2F053dbda1-b68f-07d0-4425-c58d1196b0ca.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&w=1400&fit=max&s=1b32081f034a1fd5a733c914e9a0bea5

③ 階層的に情報を管理可能

階層構造イメージ
Notionの階層構造

④ ページとDBという2つのドキュメント形態を持っている
  • ページとは
    • ドキュメントの文字や画像を挿入したりすることが可能な形式
  • DBとは
    • そのまま、データベースとしての形式
    • 1つのアイテム(レコード)に対して、詳細情報としてページを設定可能

DBのビジュアライズ
DBのビジュアライズ

「Notionとは?」のまとめ

Notionとは、「ほとんど無料で」なんかいい感じにマークダウンでドキュメントを書いて共有できるツールです。 (超適当)

第2章: プロセカとは?

正式名称は「プロジェクトセカイ カラフルステージ! feat.初音ミク」で、SEGAとColorful Paletteが共同開発したスマホ用の音ゲーです。

pjsekai.sega.jp

こちらのゲームは、2019年08月30日の初音ミク「マジカルミライ 2019」 にて、企画の開始が公表され、翌年(2020年)09月30日にリリースされ、その年の「Google Play ベスト オブ 2020 日本版のユーザー投票部門」にて最優秀賞に選出されました。(参考: Google Japan Blog: Google Play ベスト オブ 2020 本日発表 )

ゲームの情報とか細かいところ等は、有志によるWiki↓がものすごく発展してきているため、そちらを参考にしてみてください。

pjsekai.com

※ 本記事ではエンジニア視点で、実際に遊んでみて、思ったすごいところや、注目している点をピックアップして行きます。

ピックアップ!!

① 3DMVがすごい

こちらは、ココ最近のスマホバイス自体のスペックが著しく向上しているところも関与しているかと思いますが、作成しているモデルと、そのモーションを正確にキャプチャする技術に着目したいところです。
モーションに関しては完全に推測になりますが、おそらくSEGAモーションキャプチャスタジオを利用しているのではないかと思っています。
また、アクターの動きに関しても、ダンサーさんがそれぞれレベルが高く、かつ各キャラクターを意識して動いていることがMVを見ていると感じ取ることができます。
また、MVのカメラワークに関しても着目すると、「あれ? これ普通にガチのMV作ってる感じのMVじゃね?」と感じるわけです。
もちろん、リアルのMVを取ろうとしたときは実際に歌手の方に対して様々な角度からリアルに撮影するわけですが、プロセカはリアル空間で撮影することはできません。(できたらとっても楽しそうですが…。)
つまり、「3Dのカメラワークに詳しくて、実際のライブのカメラワークにも詳しいカメラマンが撮影しているんだなぁー」と推察できます。
バーチャルなキャラクターが増えているこのご時世を考えると、とても貴重なスキルを有しているなぁと思わざるを得ませんね。

② バーチャルライブがすごい

上記の3DMVをライブのように、複数のユーザーと一緒に楽しむことができるコンテンツです。
これは言語化しづらいのですが、とにかくMVのモーションがどれほど細かく作成されているかよくわかります。
あとは、ココ最近特になのですが、ライティングの技術が特に向上していて、楽曲にとてもマッチした演出がされていて、まさに「ライブ感」を感じ取ることができます。
また、コネクトライブという、普通のライブで言うところの「ファンサ」も実現されるという、バーチャルライブのリハーサル公演が行われました。( NEWS | プロジェクトセカイ カラフルステージ! feat.初音ミク )
※ 下記画像はその時のものです

コネクトライブの模様

③ ノーツ譜面などに遊びが隠れている

  • 「千本桜」: 黒うさP
    • EXPERTのコンボ数がちょうど1,000
  • 「KING」: Kanaria
    • 歌で「You Are King」のところで「Y R K」をかたどったノーツが流れてくる
  • 「39みゅーじっく!」: みきとP
    • すべてのレベルで、コンボ数の下2桁が39に統一
  • 「みくみくにしてあげる♪【してやんよ】」: ika_mo
    • ネギを模ったノーツや、「39」「みく」を模ったノーツが落ちてくる
  • 等など…

こちらに関しては、これ以外にも大量に隠されて(?)いますので、ぜひ皆さん遊んでみて色々な楽曲を確認してみてほしいです。

音ゲーじゃないところに何故か力が入っている

プロセカ内でもいろいろな機能があるのですが、特に各ユーザーごとにプロフィールを設定する画面があるのですが、このカスタムプロフィールが完全にMicr●soft P●werPointと似たような機能を有しています。
オブジェクトのグルーピング機能こそまだ実現していないものの、レイヤーの設定や透明度の設定など、「あれ? これ音ゲーじゃなかったっけ?」と思うこともしばしばです。

また、バーチャルライブの待機画面ですが、今でこそブランコやベンチ、滑り台やミニライブ会場など色々な物が置いてありますが、リリース直後は本当になにもない場所でした。
その場所に、ある日突然「サッカーボール」が実装されました。
こちら後々のワンダショチャンネルで発表されていた内容によると、「エンジニアが遊びで作ったやつがそのまま採用されてリリースされた」らしいです。
ガチガチのウォータフォール開発をしている企業だったら考えられない話ですよね?
エンジニアが伸び伸びと楽しそうに開発しているのかなーと思い、すごくエモい気分になりました。

「プロセカとは?」のまとめ

プロセカとは、初音ミク鏡音リン・レン巡音ルカKAITOMEIKOなどのVolcaloidとともにVocaloid楽曲やボカロPの描き下ろし楽曲を楽しんだり、ライブを楽しんだりすることができる、すごい音ゲー。 Let's Download and Ckeck it out!!
(超適当説明 Again)

第3章: プロセカのNotionページ作って公開しました!!

proseka.notion.site

極論、このページを作ってやりたかったことは、

  • プロセカの楽曲リスト作ってちゃんと効率曲調べたい
  • 遊び要素等も、もっときちんとデータ化してまとめておきたい
  • どうせならもっとビジュアライズして見てて楽しそうな楽曲のリストを作りたい
  • DBなんだから、色んな所から参照されて活用できるようにしたい

という点に尽きます。

Notionという媒体自体がとてもクレバーな表示をすることが可能なので、Notionの機能を120%活用して、プロセカの情報をまとめていきたいと思います。

2022/06/13追記

Notinoのリンクを更新していたので、こちらのリンクも更新しておきました

現状と今後

現在、各種DBを設定し、基本的な楽曲情報の登録を済ませています。
今後は、このページのDBをより拡張し、

  • 歌唱グループごとにグループ化して、分析したり
  • AnotherVocalのうち、誰がどの曲を歌っているのか一覧表示で確認したり
  • 時間毎のポイントが高い楽曲を分析したり
  • 1秒あたりのノーツ数を分析したり

いろいろな観点から楽曲を分析していきたいと思っています。

募集

現状まだ実現できていませんが、共同編集者を今後募って、こちらのページの発展を進めたいなーと考えています。
「興味がある!」「やってみたい!」という方は 編集者Portal のページにて、コメントを残していただけるとありがたいです。

最後に

謝辞

今回、このNotionのページのデータを収集するにあたって、9割以上の情報をプロジェクトセカイ攻略Wiki様から引用させていただいております。
本当にありがとうございます。

個人的には、プロジェクトセカイ攻略Wiki様には、プロセカに関する網羅的な情報を、
こちらのNotionでは、より楽曲に焦点を当てて、その分析ができるような情報を集約できればと思っています。

React × Next.jsと学んできたので、TypeScriptもキャッチアップしてみた

ご挨拶

皆さん、こんにちは。
前回、前々回と、React × Next.jsのご紹介をしました。

dtm3110.hatenablog.com

dtm3110.hatenablog.com

今回はその第3段として、TypeScriptに関してご紹介します。

TypeScriptとは?

TypeScriptは、JavascriptをDDD(Data Driven Development)の文脈で開発する際にとても便利なツールです。
データを取り扱う際、そのデータの型を厳格に定義しておくことで、読みやすさ、リファクタリングのしやすさ、エラー・バグの抑制といった様々な利益を享受することができます

型の定義方法

InterfaceType

型を定義する際、intercacetypeという2つの方法があります
詳細は↓のQiitaの記事がとても良くまとまっていたので、ぜひ参照してみてください TypeScriptのInterfaceとTypeの比較 - Qiita

まとめのtableだけパクリスペクトさせていただきました↓

Interface Type
用途 クラスやオブジェクトの規格を定義 型や型の組み合わせに別名を付ける
継承 交差型で同じことができる
同名要素
宣言
マージされる エラー
Classへの
implement
交差型
共用体型
タプル型
Mapped Types
規定しない
プロパティ
他にもプロパティが
存在しうるものとして扱う
存在しないものとして扱う
スコープ 宣言されるとGlobalへ exportしない限りプライベートでしか使われない

Interface構文は初期のTypeScriptから使われている構文であり、逆にtype構文は比較的新しい記載方法です。
プロジェクトにもよるかと思いますが、最近はType構文で統一されることが多いように思われます。
スコープがプライベートなので、Typeのほうがルール決めして運用しやすいこともよく使われる要因でしょう。

d.tsファイル

型の定義を外出しにしたファイル

export type User = {
  id: number
  name: string
  email: string
}

export type UserRole = 'Admin' | 'Manager' | 'User'

型の種類

基本的&直感的にわかりやすいものリスト

Type Example 備考
string typeof "text" === "string" "String"じゃないことに注意!
number typeof 10 === "number" こちらも"Nmber"じゃないことに注意!
array Array.isArray([0, 1])
  • 配列であるときに使われる。
  • これも"Array"じゃないことに注意!
object tyoeof {key: "hoge"} === "object"
  • 定義される対象がobjectであるときに使われる。
  • これも"Object"じゃないことに注意!
  • 実際はObject内のKey毎に型定義することが多い
boolean typeof true === "boolean" trueまたはfalseしか入らない
undefined typeof undefined === "undefined"
  • nullとは違うことを忘れずに
  • type hoge?: string とすると
    string型もしくはundefined型という定義になる
  • ※変数自体が定義されていないものがundefined
functions typeof () => { true } === "number"
  • 指定した要素がfunctionであるときに使う
  • HandlerなどでFunctionが帰ってくるときなどに使われる
null typeof null === "null" undefinedとは違って、定義されているがデータがnull

union型

特定の型が唯一には決まってないけれど、取りうる型が決まっている場合に用いる型定義
複合型と言われることもある

const union: string | number = "foo";
const unionMulti: string | number | null = null;

タプル型

JavascriptにはそもそもTupleっていう型はないんですが、Arrayを使うことにより、TypeScriptでも宣言できるようになっています。
※ちなみに、Tuple型はLisp, Python, Haskell, C#などで使われる型です

const tuple: [string, number] = ["foo", 3]; // Note: OK!

const tuple: [number, string] = ["foo", 3]; // Note: NG!! → [3, "number"]

any型

とりあえずどんな型でもいいよっていう型
TypeScriptの思想を壊しかねないので、本当に「使わないと実装できない!!」ってとき以外使わないようにしましょう

void型

typeof null === "null"
または
typeof undefined === "undefined" | 型が存在しない場合の型
nullとundefinedのみ
const voidType: null | undefined と同義 |

〇〇の配列

公式ドキュメントでは明示的に記載されてませんが、↓のような形を宣言する際に利用されたりすることもあります

const stringArray: string[] = ["aaaa", "bbbb"]

interface customObject {
  name:string;
  id: number
}
const objectArray: customObject[] = [
  { name: "Hajime", id: 1 },
  { name: "hoge", id: 2 }
]

また、上記のような方法ではなく、次に示すGenerics型で記載する場合もあります

Generics

変数を渡すことによって、推論する型を指定できる方式

// NOTE: Arrayはデフォルトで用意されているgenerics型で、`<>`内に指定された型の配列を定義する
type stringArray = Array<string>
const arr: stringArray = ["aaaa", "bbbb"]
interfase Backpack<Type> {
  add: (obj: Type) => void;  // Note: 引数に指定された型(Type)を取り、Voidを返す関数
  get: () => Type;           // Note: 指定された型(Type)を返す関数
}
// Note declareは初期値を指定しないで宣言するときに使うTypeScriptの宣言構文
declare const backpackString: Backpack<string>;
backpackString.add("hoge");
console.log(typeof backpackString.get() === "string");

declare const backpackNumber: Backpack<number>;
backpackNumber.add(28);
console.log(typeof backpackNumber.get() === "number");

その他

ほかにもEnum型やUnknown型、Never型などがあります
詳しくは↓こちら

www.typescriptlang.org

振り返りテスト

f:id:DTM3110:20210218114350p:plain 学んだことがきちんと身になってるかどうかを確認するための、簡単な型定義テストを作ってみました。
ご興味のある方はぜひやってみてください!

Q1: 次の変数に当てはまる型UserをType構文で記述せよ

定義したい変数

const user: User = {
  id: 0,
  name: 'Hajime Saito'
}

回答&解説 (CLICK HERE!)

// 1点の回答
type User = object

// 3点の回答
type User = {
  id: number,
  name: string
}

回答は上記の通り。
変数userは確かにobjectの型ですが、Object内の型の定義ができていないため、object型を宣言せず、Object内の各要素ごとに型を宣言してあげるのがBetterです。

Q2: 次の変数に当てはまる型UserListをType構文で記述せよ
なお、Q1で作った型を必ず利用すること

定義したい変数

const userList: UserList = [
  {
    id: 0,
    name: 'Yuji Itadori'
  },
  {
    id: 1,
    name: 'Megumi Fushiguro'
  },
  {
    id: 2,
    name: 'Satoru Gojo'
  },
]

回答&解説 (CLICK HERE!)

// 必須利用
type User = {
  id: number,
  name: string
}

// 0点の回答
type UserList = [User, User, User]

// 3点の回答
type UserList = User[]

// 3点の回答
type UserList = Array<User>

回答は上記の通り。
正直0点の回答は正解にしたくないですが、TypeScript的にはエラーを出さないので、一応0点としました。
(なお、何故正解にしたくないのかという問題がQ4になります。)

3点の回答2つについて

今回はQ1で定義されたuserを要素に持つ配列の型定義でした。
「配列の中にUserが含まれる」という定義になるので、User[]もしくはArray<User>が正解となります。
この2つの定義方法ですが、公式も同列に紹介しており、その中身的な差異はありません。
趣味で使い分けることになるでしょう(ただ、○○[]のほうが圧倒的に打込み量が少なく、楽なのでこっちを使っている場合がお多いように思います。)

Q3: 次の変数に当てはまる型UserListをType構文で記述せよ
なお、Q1で作った型は利用しないこと

定義したい変数

const userList: UserList = [
  {
    id: 3,
    name: 'Jogo'
  },
  {
    id: 4,
    name: 'Hanami'
  },
  {
    id: 5,
    name: 'Dagon'
  },
]

回答&解説 (CLICK HERE!)

// 0点の回答
type UserList = [object, object, object]
type UserList = [
  {
    id: number,
    name: string
  },
  {
    id: number,
    name: string
  },
  {
    id: number,
    name: string
  }
]
// 1点の回答
type UserList = object[]
type UserList = Array<object>

// 3点の回答
type UserList = {
  id: number,
  name: string
}[]

// 3点の回答
type UserList = Array<{
  id: number,
  name: string
}>

回答は上記の通り。
0点の回答は一応TypeScript的には通ってしまうので、回答として追加しましたが、個人的に嫌いなので0点としてます。
1点の回答はQ1での解説と同様になるのですが一応コンパクトにかけているので、お情けで1点としています。
3点の回答はQ2での回答に対してQ1の回答を適応する形です。
基本的に3点の形で書くようにしたほうが良いでしょう。

Q4: Q2, Q3で0点となった次の2つの型定義に関して、語句を埋めよ

おすすめされない型定義

type UserList = [User, User, User]

配列の宣言において上記のような宣言をした場合、厳密には配列(Array)の型宣言ではなく【AAAAA】型の型定義である。
なので、UserListを用いて変数userListを宣言した場合【BBBBB】つ目の要素を追加したときにエラーが発生する。
また【AAAAA】型なので、下記のようにUserList2を定義すると変数hogeListにUserList2の型を当てて定義することができる。

type UserList = [User, User, User, 【CCCCC】]
const hogeLIst = [
  {
    id: 6,
    name: 'Kento Nanami'
  },
  {
    id: 7,
    name: 'Aoi Todo'
  },
  {
    id: 8,
    name: 'Suguru Getou'
  },
  9
]

回答&解説 (CLICK HERE!)

【AAAAA】: タプル 【BBBBB】: 4 【CCCCC】: number

回答は上記の通り。
解説は文章がそのまま解説になっています。
もちろん、タプル型の宣言になっているので、Arrayっぽく書いても要素数は固定なので、配列としては使えません。
また、デフォルトのデータの要素数が1の場合、[User]としてしまっても、一応通ってしまうので、デバッグするときにとても厄介です。
なので、配列の型宣言をするときは、「タプル形で書いちゃってないかな?」というのを一度立ち止まって確認してみることをおすすめします。

最後に

今回はTypeScriptの紹介ということで、各種型に関して簡単に紹介した後に振り返りテストと言う形でご紹介しました。
「これどんな型だったっけ?」というときに確認するツールとして利用していただけると嬉しいです。

今回、React, Next.js, TypeScriptと3つのキャッチアップを実施しました。
次の記事では、↑これらのキャッチアップの実施理由と、それに伴う開発までの記事を、下記ブログで1つ書こうと思っています。

tech-blog.abeja.asia

ぜひお楽しみに!

Reactのキャッチアップをしたので、今度はNext.jsを学んでみる

ご挨拶

皆さん、こんにちは
先日、 dtm3110.hatenablog.com こちらのブログを投稿しました。
今回はその続きでNext.jsに関してキャッチアップしてみましたので、前回と同様にまとめてみようと思います。

そもそもなんでキャッチアップしたのん?

この質問に関しては、前回のブログと同様に近日中にこちらのブログでご紹介しようと思います!!

tech-blog.abeja.asia

乞うご期待!!!

キャッチアップ内容

キャッチアップし始める際、いつもどおり、Next.jsのチュートリアルである「 Create a Next.js App | Learn Next.js 」を実施しました。
基本的にはこのチュートリアルのみを実施しましたが、とても良くNext.jsの機能や使い方がまとめてありましたので、Next.jsを学習する方はぜひぜひしっかりこのチュートリアル見て、触ってみてください。 今回はNext.jsの中でも、一番の山場になりそうな「Data Fetching」の機能を中心に下記のような機能をそれぞれご紹介します。

# カテゴリ 対象(略称)
1 Data Fetching Static Generation (SSG)
2 Data Fetching Server-side Rendering (SSR)
3 Data Fetching Single Page Application (SPA)
4 Data Fetching それぞれの特性まとめ
5 routing Next.jsの基本的なディレクトリ構成と役割
6 API Next.jsのAPI

1. Static Generation (SSG)

f:id:DTM3110:20210120175444p:plain

下の表にある通り、Build時にClientユーザーがアクセスするファーストビューのHTMLを生成しておく処理手法。
Clientユーザーがアクセスした際、外部データへの接続(API Call & データ取得)などの処理や、そのデータを用いたHTMLファイルの生成といった処理をせずに、そのまま生成済みのHTMLファイルを取得するため、「ファーストビューを表示する」という観点では、以降に説明する2つの方式より圧倒的に早い。
一方、Build時にデータごとHTMLファイルを作成するという仕様上、リアルタイムデータを用いるようなWebページを表示するのには適していない。
もし仮にリアルタイムデータを使いながらSSGでレンダリングする場合は、固定データのみSSRでBuildさせ、HTMLファイルを読み込み後にClient-side(SPA)側からAPIをコールして生成するような形になる。

Key Contents
正式名称 Static Generation
イメージ
概要 Build時にファイルを生成する方式。ファーストビューがとても早い。
データ読込関数 一括取得: getStaticProps
動的ページでの取得: getStaticPaths
メリット Build時にHTMLを生成し、クライアント側からアクセスされた際にすぐにそのHTMLを返すことにより、ファーストビューを高速に表示する事ができる
デメリット 頻繁なデータ更新があるサイト(Twitter等のSNSや)
ユースケース データの更新が頻繁ではないが、ファーストView内にデータ量が多いwebページを表示する場合(データサマリー画面など)

補足(getStaticPropsgetStaticPathsの違いと使い分け)

getStaticProps getStaticPaths
利用条件 ページ内のコンテンツに
外部データを含む
ページのパス自体に
外部データを含む
利用パターン 全体サマリー画面などとして利用されることが多い。 詳細画面などとして利用されることが多い。
備考 コンテンツ内のデータを取得。単体でも使えるが、idを引数として持ってgetStaticPathsで取得したキーから該当のデータを参照したりもする getStaticPathsで対象のIDなどのキーを取得し、getStaticPropsでそのキーを受け取って、該当のデータを表示」といったあわせ技が中心

2. Server-side Rendering

f:id:DTM3110:20210120175732p:plain

Clientユーザーがアクセスした際に、サーバ側でAPIのCall等をしてデータを取得し、表示用のHTMLファイルを返す処理手法。
Backend for Frontend(BFF)の思想が、「Client側のCallに対してFrontendで必要なデータ等を取得・整形して返すBackend」ということから、SSRはBFFの一種と言っても良い(ClientユーザーのCallに対して整形済みのHTMLを返すため)。
こちらの手法では、サーバ側で必要なデータのAPI Callを実施するため、Clientの利用しているデバイスや通信環境等による影響を受けない。
またSPAと違い、各種APIのレスポンスに含まれる不要データを一次取得するといったこともせず、サーバ側で整形され生成されたHTMLを取得するので、Clientユーザーのデータ通信量的にも優しい。

Key Contents
正式名称 Server-Side Rendering
イメージ
概要 Clientからのアクセス時にHTMLを生成する方式。役割上、BFF(Backend for Fronend)としてフロントエンドのためにHTMLファイルを生成してClientに返している。
データ読込関数 getServerSideProps のみ
メリット HTMLを生成するのはNext.jsのServer側なので、閲覧する端末の処理速度に依存せずに画面を生成することこができる。Server上でAPIとの疎通もあるので、クライアント側からコールするより処理速度は早くなる(ハズ)
デメリット アクセスしたあとにHTMLを生成するので、ファーストビューはどうしてもSSGより遅くなる
ユースケース データの更新が頻繁に行われており、複数のデータソースへのアクセス(API)を利用している

3. Single Page Application

一つのHTMLファイルを受け取り、Clientユーザーのデバイス上のJavaScriptから各種データを取得し、そのデータをもとにHTML内にデータ表示することで画面を表示する手法。
画面遷移をなくすことで、サーバーとの疎通を最小限にし、Clientユーザー側ではアクションに応じたデータ取得だけをすることで、ブラウザに依存しないユーザー体験を提供することができる。

Key Contents
正式名称 Single Page Application
Next.jsでは Client-side Rendering
イメージ
概要 クライアントユーザーがリクエストした際、空のHTMLを返し、JavascriptによるAPIのCallで各種データを取得、Viewを表示する方法。
データ読込関数 各種APIをクライアント側でCallして取得
メリット 画面遷移がないため、ブラウザ自体の挙動に依存せず、高度なWeb表現(ユーザーアクションがなされた場所だけデータを更新など)が可能
デメリット クライアント側でデータをそれぞれ取得しに行くため、ファーストビューは致命的に遅い。
クライアント側のデバイスによって通信速度の差が現れ、APIのレスポンスすべてをクライアント側で処理するため、BFFなどが間にない場合はデータの通信量が肥大化する
ユースケース SNSの新規メッセージ表示などのリアルタイムデータの表示

4. それぞれの特性まとめ

f:id:DTM3110:20210124223759p:plain

  • 略図説明
    • SPA
      • Clientからのリクエストにより空のHTML取得後、Clientのデバイス上からAPI経由でデータ取得し表示
      • Next.jsではClient-side Renderingと言われている
    • SSR
      • ClientからのリクエストによりServer(Next.js)側でHTMLを生成、このときServer内でAPIをCallするため、Client側にネットワーク的な負荷はあまりかからない
    • SSG
      • Build時にすでにAPIをCallし、データを入れた状態でHTMLを生成しておき、Clientからのリクエスト時に、即座に生成済みのHTMLを返却、SSR同様Serverないでファイルが生成された状態なので、Client側にネットワーク負荷があまりかからない
  • First View描画時間
    • SPA
      • ServerからからのHTMLを取得するのは早いが、その後のデータ取得で各種APIをCallするため、処理がデバイスに大きく依存
    • SSR
      • リクエスト時に各種APIをCallしてHTMLを生成するため、SPAよりもHTMLファイルの取得は遅いが、完成されたHTMLが返却されるためClient側のスペックに依存しない速度で描画が可能
    • SSG
      • Build時に各種APIをCallしてHTMLを生成し、Clientがアクセスした際に生成済みのHTMLを返すだけなので、爆速
  • リアルタイムデータの扱い
    • SPA
      • Client側のアクションを即座に反映してAPIをCallすることが可能
      • SEOが関係しないようなユーザー個々のページ(ダッシュボード)などに有効
    • SSR
      • BFFと同じ働きをするため、Client側から各種APIを叩くより通信量が抑えられる
      • もちろんリアルタイムデータの扱いは得意
    • SSG
      • Build時にすでに完成されたHTMLを生成しているので、データ自体を更新するためには再Buildが必要
      • リアルタイムデータの扱いは不向き

使い分けの仕方

First Viewを最速で表示することは、UX的にもSEO的にも重要です。伴ってSSGはとても強力な手法と言えます。
一方、リアルタイムに変動するデータ(SNSや株情報など)や、HTMLを取得した後に判定するもの(Auth情報)がある場合はSSG(もしくはSPA)を利用する必要があります。 結論、各ページにたいして、そのページで利用されるデータがどのタイミングでどのように利用されるデータなのか考えながら、適切な手法を適応していくことが重要です。


4. Next.jsの基本的なディレクトリ構成と役割

ディレクトリ構成は各プロジェクトに任されている部分が多いですが、その中でもだいぶポピュラーな部分を抜粋して紹介します。

ja.reactjs.org

root/
  ┠ pages/
  ┃  ┠ _app.js(.tsx)
  ┃  ┠ _document.js(.tsx)
  ┃  ┠ api/
  ┃  ┃  ┗ hogehoge/
  ┃  ┃     ︙
  ┃  ┃     ┗ index.js(.tsx)
  ┃  ┠ hogehoge/
  ┃  ┃  ︙
  ┃  ┃  ┗ index.js(.tsx)
  ┃  ┠ 404.js(.tsx)
  ┃  ┗ index.js(.tsx)
  ┠ components
  ┃  ┠ 〇〇.module.css
  ┃  ┗ 〇〇.js(.tsx)
  ┗ public/
名称 Type 説明
pages Directory 外部からアクセスできる(Routing)されるファイルを格納するDirectory
このDirectory内の階層がRoutingのpathになる
_app.js(.tsx) File 全ページに関わる初期化処理を指定する
例)
  • 共通のレイアウトの指定
  • 共通のState管理(Auth情報とか)
  • etc...
※この処理はSPA(Client-Side)で稼働するので注意
_document.js(.tsx) File 全ページに関わる初期化処理を指定する。中でも、HTMLのメタタグやHTMLの大本の構成を定義する。
_app.js(tsx)と異なり、こちらはSSRでのみ実行されるため、Client側の処理を記述はしないように注意
例)
  • 共通のレイアウトの指定
  • 共通のState管理(Auth情報とか)
  • etc...
※この処理はSPA(Client-Side)で稼働するので注意
api Directory APIの処理部を記載するDirectory
階層構造がそのままAPIのエンドポイントになる
Dynamic API Routeの場合はhandlerにqueryを記載し、それに合わせたファイル名(/api/posts/[postId].js等)を指定する必要がある
詳しくはこちら
404.js(.tsx) File Routingで一致しなかった場合に出力される画面の記述
pages/index.js(.tsx) File ホーム画面を記述するファイル
components Directory コンポーネントとして分離したファイルを格納するDirectory
用途によってどのように下位Directoryを設計するかがポイント
スタイルなどもここにまとめる事が多い
〇〇.module.css File CSSモジュールを利用する場合はファイル名をこの形式にする必要がある
public Directory 主にfaviconや、画像ファイルなどのメディアを格納するDirectory

5. Next.jsのAPI

  • next/link
    • クライアント側のナビゲーション
    • SPAの画面遷移
    • デフォルトで遷移先画面のプリフェッチをするため、描画が早い
  • next/head
    • HTMLのヘッダー内のメタデータとかを設定できる
    • お作法として、タグが重複Renderingしないようにkeyプロパティを入れる
    • 格納するメタタグたちは、Headの直下に置く必要がある
  • next/router
    • routerObjectを使うには useRouterを呼び出す必要がある
    • Reactフックでつかうため、クラスでは使えない
    • router.prefetchという、プリフェッチ機能がある(next/linkではデフォルトでプリフェッチするので、next/routerでは明示的に利用する必要がある)
      • 使用例:ログインページ →(ここでprefetch使う)→ Dashboardにリダイレクト
  • next/document
    • _document.js(.tsx)で使う、HTML拡張用のAPI

最後に

チュートリアル最初の「Create a Next.js App」を軽く目を通して見て、Vue.jsを主に使って開発していた感覚からすると、
Next.jsは大枠でみると、「Vue-cilの役割とVue-routerの役割を担っているReactのフレームワーク」という認識でした。

一方で、First-Viewを早くするためのData Featching周りの機能や、コードの分割機能等のよりユーザビリティを考えたUXを構築するための機能が結構充実しているということがわかりました。

今後は最適なDataFetching方法を考えたりしながら、実際にアプリを作ることで実際の使い方を身に着けていく予定です。

Vueしか触ってこなかったエンジニアがReactを触ってみた

ご挨拶

皆さん、こんにちは。
今回ですが、今まで、Vue.jsばっかり使って開発してきましたが、そろそろReactも本腰を上げてキャッチアップを進めようと思い、
「どうせならBlogにしておいたほうが振り返りしやすいかな?」
ということで、Reactのキャッチアップの概要を簡単にまとめていきたいと思います。

f:id:DTM3110:20210201173347p:plain
隣のフレームワークは青い

そもそもなんでキャッチアップしたのん? (2021/02/03 15:58追記)

この質問に関しては、近日中にこちらのブログでご紹介しようと思います!!

tech-blog.abeja.asia

乞うご期待!!!

キャッチアップ内容

「ご挨拶」で意気込んでみましたが、『VueエンジニアがReactのキャッチアップをする』的な記事は星の数ほどあるので、今回の記事では『「私が」どのようにキャッチアップしたのか』にフォーカスを当ててご紹介します。

1. Tutorial: Intro to React – Reactを実施

こちらの記事は、React本家本元のチュートリアルです。
「Reactとはなんぞや?」から「基本的にはどうやって使うの?」ということを一通り体験し、学ぶことができました。
このチュートリアルを実施せずに『React 勉強しました!』という人はいないでしょう。

Reactの書き方の概要

// NOTE: React.Componentを継承することで利用可能
class Board extends React.Component {
  // NOTE: constructorによる初期値(props)の代入が可能
  constructor(props) {
    super(props);
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true
    };
  }

  // NOTE:  クリック処理などの処理関数をClassの関数として定義可能
  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }

  // NOTE: "(<描画する要素>)" のようなJSXの形式にすることによって要素自体を返り値とすることが可能
  renderSquare(i) {
    return (
      <Square
        value={this.state.squares[i]}
        onClick={() => this.handleClick(i)}
      />
    );
  }

  // NOTE: いわゆるMain関数で、Vue.jsで言うところの"<template>"に類する
  render() {
    const status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');

    return (
      <div>
        <div className="status">{status}</div>
        <div className="board-row">
          {this.renderSquare(0)}
          {this.renderSquare(1)}
        </div>
        <div className="board-row">
          {this.renderSquare(2)}
          {this.renderSquare(3)}
        </div>
        <div className="board-row">
          {this.renderSquare(4)}
          {this.renderSquare(5)}
        </div>
      </div>
    );
  }
}

読了後に掴んだイメージ

VueはComponent内でHTML成分を先に当て、その中にデータを入れて整形
Reactはデータごと生成してHTMLに追加し整形
そんなイメージ

f:id:DTM3110:20210201194312g:plain
それぞれのHTML生成イメージ

2. Vue.jsエンジニアのためのReact入門 | Hypertext Candy を読む

こちらの記事はReactとVueのそれぞれの立ち位置に立って、何をどのように実現するかを対比する形で記載しています。
もともとVueを書いてる人がReactを触り始めるにはもってこいの索引になるでしょう

上記記事の一部抜粋

機能 Vue.js React
Component <template /> <script /> <style />をそれぞれ記述 関数型クラス型の2種類の記述方法がある
JSXという拡張構文を返す
Component Method <script />内に methodsを定義 JSXで表現
Template <template /> を利用
変数を使う場合は{{}}を使ったり、v-if v-forなどを使う
JSXで表現
普通にJSでタグを生成していく感じ
変数を展開する場合は{}を利用
Action Events @click="handleClick"@submit.prevent="handleSubmit"のv-on要素を利用 onClick={handleClick}のように記載
Input Form v-modelを利用 onChangeハンドラーを利用して自作
ref refを利用し一意のキーを用いてアクセス useRefを利用しDOMへの参照用の変数を作成
computed computedを利用 JSXで表現
主にonChangeハンドラーを利用して自作
watch watchを利用 JSXで表現
基本的に変更検知は存在しない
created createdを利用 関数型
functionのreturn前の処理
クラス型
constructorの処理
mounted mountedを利用 関数型
useEffectを利用して登録
クラス型
componentDidMountを利用
pops propsを利用 関数もしくはconstructorの引数から取得
emit $emitを利用 propsとして関数を渡し
それをCallする

読了後に掴んだイメージ

Vue

良くも悪くもいろいろな機能をもともと内包しており、
良く言えば「きちんとしたフォーマットに従って書くことできれいに書ける」形式。
悪く言えば「機能過多かつ形式張っていて柔軟性に乏しい」形式。
と言えるかもしれません。

React

Vueとは打って変わって、殆どフォーマット化された機能は有しておらず、JSX形式でJavaScriptを用いていろいろな機能を自身で作っていく形式になっています。
なので、先程に習って述べるなら、
良く言えば「限りなく自由度と拡張性が高く、独自形式で記述できる」形式。
悪く言えば「フォーマットがないために、複雑かつ読解困難になってしまう可能性がある」形式。
といえます。

3. I created the exact same app in React and Vue. Here are the differences. [2020 Edition] を読む

※ 2019年版だと日本語翻訳&要点書き出し版( ReactとVueの比較、全く同じアプリを作成してみて分かった相違点 2019年Edition | コリス )があるらしい

読了後に掴んだイメージ

実際にソースコードを確認しながら、『2.Vue.jsエンジニアのためのReact入門』の内容を確認できる感じの記事。
日本語版にあるようにまさに『隣の芝生は青く見える』といったもので、VueもReactもそれぞれ長所短所があり、それぞれの癖があるというのがよく分かる 記事になっています。

単純にフレームワークとして『Vue VS React どちらが良いか?』というのは、やはり判断が難しく、
『何を実現したいか?』↓
『そのためにどんなコンポーネント(機能)をもたせる必要があるか?』↓
『それが実現しやすいフレームワークは何か?』
みたいな感じで、最終的にどうしたいのかベースで実装していけるのが良いのではないかと感じました。

最後に

色々キャッチアップしてみて感じたのは、やはりどちらのフレームワークもある種のの理念を持って構築されているために、その理念さえ理解すればどちらも使いやすいということです。
これは実装者の性格が出るような問題なので、この記事では『どちらが良い』みたいな結論は出しませんが、「どのフレームワークがどんな理念で積み上げられていて、作りたいシステム(もしくは一緒に作り上げていくチーム)はどちらのフレームワークが合っているのか?」といったところを検討した上で、どのフレームワークを使うのかを決めるのが重要だと思います。

2021年もよろしくお願いいたします

新年あけましておめでとうございます

皆さん、あけましておめでとうございます。
毎年恒例のシェル芸をやろうかと思ってたんですが、今年は面白いツールがあったのでそのご紹介です!

今回ご紹介するのは TextAliveという、動画と歌詞があれば動画を作ることができるシステムです。

作ったやつ

f:id:DTM3110:20201231234942p:plain

https://textalive.jp/videos/6010

2021/01/03 追記

微調整して出来上がったので、そちらも載せておきます。

本家動画様


wowaka 『アンノウン・マザーグース』feat. 初音ミク / wowaka - Unknown Mother-Goose (Official Video) ft. Hatsune Miku

良かった点

  • 単純にテンプレートがあるのでそれを組み合わせて動画を作ることができる
  • リアルタイムプレビューがいい感じ
  • Javascriptがかけるともっと細かく実装できる(←これがマジ神機能)
  • APIがあって、別アプリと連携させることができる
  • 歌詞に対して解析をかけて、おおよそのタイミングを合わせて文字出力をしてくれるようになっている
    • もちろん詳細設定も可
  • 裏側にいるエンジニアに要望を機能ごとに出せる
  • Javascriptで実装したらその部分をコミットして運営に見てもらえる(←これもやばい)

惜しい点

  • 保存するときに完全に新規保存しかないので、更新とかが難しい
  • うっかりブラウザ落ちると全部落ちる(多分キャッシュ化ストレージで記録してる疑惑)
  • 歌詞の解析が若干微妙
    • 自分が作っったやつも作成時間の70%が歌詞のタイミング合わせでした

総括

惜しい点に関しては普通に裏側にいるエンジニアに要望を出すことができるので、解決していきそう。
単純につかってみて楽しかったので、みなさんもどんどん遊んでみてはいかがでしょうか?

ABEJA Advent Calendar 2020書きました

表題の通り今年もAdvent Calendarを書かせていただきました。

f:id:DTM3110:20201207030517p:plain

「エンジニア育成教材」または「ガチのシステム開発ツール」としてのAppSheetという題で書いていますので、ぜひご覧ください!!!
できればLGTMも!!