React アプリを Github Pages にデプロイする方法
はじめに
React アプリを Github Pages にデプロイする方法を備忘録としてまとめます。
以下の記事を大いに参考にさせていただきました。 https://qiita.com/tat_mae084/items/745761eee6cd1d42949d
前提条件
- Node.js v18.18.0
- npm v9.8.1
- react v18.2.0
手順
アプリのひな形作成
- 以下のコマンドにより React アプリのひな形を作成します。
$ npx create-react-app my-app
package.json を編集する
my-app
配下にpackage.json
があるので、以下を追記します。- 注意点
- docs ディレクトリは root 配下に置くこと。
{ ~ 省略 ~ //homepageのURLはGithubPagesを公開した際に自動生成されるURLを入力します。 "homepage": "homepage": "https://<GitHubアカウント名>.github.io/<GitHubリポジトリ名>/", ~ 省略 ~ "scripts": { ~ 略 ~ "rm": "rm -rf ./docs", //docディレクトリがリポジトリのroot配下になるようにパスを適宜調整してください。 "mv": "mv build ./docs", //docディレクトリがリポジトリのroot配下になるようにパスを適宜調整してください。 "github-build": "npm run rm && npm run build && npm run mv" }, }
Git に push する
docs
の中に build された資材が格納されているので、ブランチに commit します。今回は main ブランチに直接 push する形を想定して記載します。- この作業が初回の push で、remote に origin を追加していない場合 remote add してから行ってください。
$ git add . $ git commit -m 'コミットメッセージ' $ git push origin main
GitHub Pages の設定を変更する
JavaScript Primer - 迷わないための入門書 (jsprimer)を読んで
はじめに
JavaScript Primer - 迷わないための入門書 (jsprimer)の感想を記載いたします。
良かったところ
- JS は、暗黙的な型変換についてかなりアバウトであることを学ぶことができました。
- 特に NaN は一度発生すると挙動的にもデバッグ的にもかなり厄介なため、NaN の防止がとりわけ重要であることを学べてよかったです。
難しかったこと
- this の扱いや、非同期処理、アロー関数の定義等一度読んだだけでは理解しきれない内容が多かったです。JS のコーディングをしていく中で辞書的に都度確認していこうと思います。
学んだこと
第一部:基本文法
- JavaScript は ECMAScript の使用によって動作が決められている。ECMAScript は毎年更新される。
- 変数宣言時に
var
を使用するのは現在非推奨。ECMAScript では機能を追加する際にも後方互換性を重視しているため、var
自体の挙動は変更されなかった。 - REPL(Read-Eval-Print-Loop)
データ型とリテラル
typeof null
が"object"
となるのは、歴史的経緯のある仕様のバグ。- テンプレートリテラル内で$
{変数名}
と書いた場合に、その変数の値を埋め込むことができる。
const str = "文字列"; console.log(`これは${str}です`); // => "これは文字列です"
undefined
はリテラルではない。undefined
はただのグローバル変数で、undefined
という値を持っているだけ。- JS において、ラッパーオブジェクトを明示的に作成する必要はない。ラッパーオブジェクトを使わずとも、ラッパーオブジェクトのプロパティを使用できる。常にリテラルでプリミティブ型のデータを表現すること推奨。
演算子
- NaN
- 数値ではないが Number 型。
- NaN はどの値とも(NaN 自身に対しても)一致しない特性がある。
Number.isNaN
メソッドを使うことで NaN の判定を行える。
// 自分自身とも一致しない console.log(NaN === NaN); // => false // Number型である console.log(typeof NaN); // => "number" // Number.isNaNでNaNかどうかを判定 console.log(Number.isNaN(NaN)); // => true
- 厳密等価演算子
const value = undefined; /* または null */ // === では2つの値と比較しないといけない if (value === null || value === undefined) { console.log("valueがnullまたはundefinedである場合の処理"); } // == では null と比較するだけでよい if (value == null) { console.log("valueがnullまたはundefinedである場合の処理"); }
- 分割代入
const obj = { "key": "value" }; // プロパティ名`key`の値を、変数`key`として定義する const { key } = obj; console.log(key); // => "value"
- falsy な値
- 以下は全て暗黙的な型変換で
false
に変換される。これらをfalsy
な値という。false
undefined
null
0
0n
NaN
""
(空文字列)
- 以下は全て暗黙的な型変換で
- Nullish coalescing 演算子(
??
)
const inputValue = 任意の値または未定義; // ||を使った場合 // `inputValue`がfalsyの場合は、`value`には`42`が入る // `inputValue`が`0`の場合は、`value`に`42`が入ってしまう const value = inputValue || 42; // ??を使った場合 // `inputValue`がnullishの場合は、`value`には42が入る // `inputValue`が`0`の場合は、`value`に`0`が入る const value = inputValue ?? 42; console.log(value);
暗黙的な型変換
- JS は、型エラーに対して暗黙的な型変換をしてしまうなど、驚くほど曖昧さを許容している。
- そのため、大きなアプリケーションを書く場合は、このような検出しにくいバグを見つけられるように書くことが重要となる。
- 真偽値の true が数値の 1 へと暗黙的に変換されてから加算処理
// 暗黙的な型変換が行われ、数値の加算として計算される 1 + true; // => 2
- JS では、エラーが発生するのではなく、暗黙的な型変換が行われてしまうケースが多くある。
- 暗黙的に変換が行われた場合、プログラムは例外を投げずに処理が進むため、バグの発見が難しくなる。
- 暗黙的な型変換はできる限り避けるべき挙動です。
Boolean への型変換
- 真偽値については、暗黙的な型変換のルールが少ないため、明示的に変換せずに扱われることも多い。
String への型変換
- 配列には join メソッド、オブジェクトには JSON.stringify メソッドなど、より適切な方法がある。
- そのため、String コンストラクタ関数での変換は、あくまでプリミティブ型に対してのみに留めるべき。
- シンボル →String への型変換
"文字列と" + Symbol("シンボルの説明"); // => TypeError: can't convert symbol to string
数値への型変換(主に NaN について)
- Number コンストラクタ関数、
Number.parseInt
、Number.parseFloat
は、 数字以外の文字列を渡すと NaN を返す。
// 数字ではないため、数値へは変換できない Number("文字列"); // => NaN // 未定義の値はNaNになる Number(undefined); // => NaN
- 任意の値から数値へ変換した場合には、NaN になってしまった場合の処理を書く必要がある。
- 変換した結果が NaN であるかは
Number.isNaN(x)
メソッドで判定可能。
const userInput = "任意の文字列"; const num = Number.parseInt(userInput, 10); if (Number.isNaN(num)) { console.log("パースした結果NaNになった", num); }
- NaN は何と演算しても結果は NaN になる特殊な値。次のように、計算の途中で値が NaN になると、最終的な結果も NaN となる。
const x = 10; const y = x + NaN; const z = y + 20; console.log(x); // => 10 console.log(y); // => NaN console.log(z); // => NaN
- NaN しか持っていない特殊な性質として、自分自身と一致しないというものがある。
- 実際に値が NaN かを判定する際には、
Number.isNaN(x)
メソッドを利用するとよい。 NaN は暗黙的な型変換の中でももっとも避けたい値となる。
- 理由として、先ほど紹介したように NaN は何と演算しても結果が NaN となってしまうため。
- これにより、計算していた値がどこで NaN となったのかがわかりにくく、デバッグが難しくなる。
意図しない NaN への変換を避ける方法として、大きく分けて2つの方法がある。
- 関数側(呼ばれる側)で、Number 型の値以外を受けつけなくする
- 関数を呼び出す側で、Number 型の値のみを渡すようにする
- つまり、呼び出す側または呼び出される側で対処するということ。どちらも行うことによってより安全なコードとなる。
- 上記の方法を行うためには、定義した関数が数値のみを受けつけるということを明示する必要がある。
- 明示する方法として以下の方法がある。
- 関数のドキュメント(コメント)として記述する。
- 引数に数値以外の値がある場合は例外を投げるという処理を追加する。
/** * 数値を合計した値を返します。 * 1つ以上の数値と共に呼び出す必要があります。 * @param {...number} values * @returns {number} **/ function sum(...values) { return values.reduce((total, value) => { // 値がNumber型ではない場合に、例外を投げる if (typeof value !== "number") { throw new Error(`${value}はNumber型ではありません`); } return total + Number(value); }, 0); }
明示的な変換でも解決しないこと
- あらゆるケースが明示的な変換で解決できるわけではない。
- Number 型と互換性がない値を数値にしても、
NaN
となってしまう。 - 一度、
NaN
になってしまうとNumber.isNaN(x)
で判定して処理を終えるしかない。
- Number 型と互換性がない値を数値にしても、
- JS の型変換は基本的に情報が減る方向へしか変換できない。
- そのため、明示的な変換をする前に、まず変換がそもそも必要なのかを考える必要がある。
空文字列判定について
- 以下のように Boolean で明示的な型変換をすると、falsy である
0
も空文字列となってしまい意図しない挙動になる。
// 空文字列かどうかを判定 function isEmptyString(str) { // `str`がfalsyな値なら、`isEmptyString`関数は`true`を返す return !Boolean(str); }
- 文字列とは「String 型で文字長が 0 の値」であると定義することで、空文字判定の関数をより正確に書くことができる。
- 次のように実装することで、値が空文字列であるかを正しく判定できるようになる。
// 空文字列かどうかを判定 function isEmptyString(str) { // String型でlengthが0の値の場合はtrueを返す return typeof str === "string" && str.length === 0; } console.log(isEmptyString("")); // => true // falsyな値でも正しく判定できる console.log(isEmptyString(0)); // => false console.log(isEmptyString()); // => false
関数と宣言
- 定義した関数の仮引数よりも呼び出し時の引数が少ない場合、余った仮引数には undefined という値が代入される。
- デフォルト引数を使わないで
||
を使って初期化するとバグにつながるので、デフォルト引数を使うべき。
文と式
- JS は、文(Statement)と式(Expression)から構成される。
オブジェクト
- プロパティの存在を確認するには in 演算子か Object.hasOwn 静的メソッドを使う
プロトタイプオブジェクト
- Object.hasOwn 静的メソッドは、指定したオブジェクト自体が指定したプロパティを持っているかを判定する。
- 一方、in 演算子はオブジェクト自身が持っていなければ、そのオブジェクトの継承元である prototype オブジェクトまで探索して持っているかを判定する。
関数と this
- this はオブジェクト指向プログラミングの文脈で JavaScript に導入された。
- メソッド以外においても this は評価できるが、実行コンテキストや strict mode などによって結果が異なり、混乱の元となる。
- そのため、メソッドではない通常の関数においては this を使うべきではない。
- コールバック関数における this は Arrow Function を使うことでわかりやすく解決できる。
Everyday Rails - RSpec による Rails テスト入門を読んで
はじめに
Everyday Rails - RSpec による Rails テスト入門の感想を記載いたします。
良かったところ
- Rails の RSpec をメインにした書籍はあまり多くないと考えられるので、本書の内容は Rails を軸におく開発者にとってとても有益のものだと感じた。
- RSpec というテスト技法一つとってもその根底には思想があり、ベストプラクティス的な RSpec の書き方があることを知ることができた。
- テストをする際の方法は必ずしも 1 つではなく、普通のコーディングと同じように様々なテストアプローチを持っておくことが効果的な RSpec を書けるようになるコツであることを学んだ。
難しかったこと
- RSpec は普通の Ruby や Rails の構文とも少し毛色が違うので、構文を覚えるのがとても大変に感じた。システムテストで使う Capybara は RSpec ともまた違う記法を使ったりもするので、RSpec をマスターするのは予想以上にコストが高そうに感じた。
- 一方で、マスターすれば効果的かつ自在なテストを書くことができる印象を受けたので、Rails を軸とする開発に携わった際には是非マスターしたいと感じた。
学んだこと
3.モデルスペック
- 期待する結果は能動形で明示的に記述すること。example の結果がどうなるかを動詞を使って説明するようにする。チェックする結果は example 一つに付き一個だけにする。
- 起きてほしいことと、起きてほしくない両方をテストすること。example を書くときは両方のパスを考えてテストを書く。
- 境界値テストをすること。もしパスワードのバリデーションが 4 文字以上 10 文字以下なら、4 文字と 10 文字、3 文字と 11 文字もテストするのが良いテストケース。
- テストを書くことは、アプリケーションの要件について見返すのに良い機会でもある。
- 可読性を上げるためにスペックを整理する。
- describe と context によりよく似た example を分類してアウトライン化する。
- before ブロックと after ブロックにより重複を除去する。
- テストの場合は DRY であることよりも読みやすいことの方が重要。
- スペックファイルのあちこちを参照しなければならない場合、ちょっとぐらいリピートしても問題ない。
4.意味のあるテストデータの作成
- Factory Bot を使うことで、データを作成する際の柔軟性を上げたり、リアルなシナリオをテストしやすくなる
5.コントローラスペック
- コントローラのテストは Rails や RSpec から完全にはなくなっていないものの、最近では時代遅れのテストになっている。コントローラのテストに限界があるためである。
- そのため、筆者が開発しているアプリケーションでは、コントローラのテストはアクセス制御が正しく機能しているか確認するテストに限定している。
- コントローラのテストは対象となる機能の単体テストとして最低限活用できるときだけ使うのがよい。使いすぎないように注意。
6.システムスペックで UI をテストする
- システムスペックは受入テスト、統合テストとも呼ばれる。
- システムスペックではたくさんの異なる部品が統合されて、一つのアプリケーションになっ ていることをテストする。
8.スペックを DRY に保つ
- テスト内や複数のテストファイルにまたがるコードの重複を減らし、テストコードを DRY にすることも重要。長い目で見たときに保守しやすいテストコードを作ることができる。
9.速くテストを書き、速いテストを書く
- モック、スタブ、ファクトリを使う等でテストをする際に様々な方法がある。これらの方法を適切に選ぶことでスペックを明快なものにすることができる。
10.その他のテスト
- メールやファイルアップロード、web サービス、バックグラウンドプロセスといった機能もテストできる。
11.テスト駆動開発に向けて
Linux基本コマンド集
Linux基本コマンド集
Linuxで基本となるコマンドについて簡単にまとめました。
cd
- change directoryの略
cd <移動先のパス>
で移動先のパスをカレントディレクトリとして移動する。
- pwd
- ls
- mkdir
- make directoryの略
- ディレクトリを作成する。
- rmdir
- remove directoryの略
- ディレクトリを削除する。
- cat
- concatenateの略
- ファイルの中身を確認できる。一度にすべて表示する。
- less
- ファイルの中身を確認できる。ファイルの中身を一部のみ表示する。
- tail
- ファイルの中身を確認できる。ファイルの中身の最後の部分を表示する。
- touch
- 存在しないファイルを指定するとファイルを新規作成できる。
- 存在しているファイルを指定しても上書きしないので安全。タイムスタンプを更新するのみ。
- rm
- removeの略
- rmコマンドを実行すると、ゴミ箱を経由せずに削除される。
- -r(recrusion)オプション:ディレクトリの中のファイルもまとめて削除する。
- -f:ファイル削除の際に警告文を表示しない。
- -i:削除前に確認してくれる。
- mv
- moveの略
- 移動先をファイル名とするか、ディレクトリのとするかで動きが変わる。
mv file flie1
:ファイル名をfile1に変更する。mv file dir/
:dirにファイルを移動する。- -i:変更前に確認する。
- cp
- copyの略
- ファイルのコピーができる。
- コピー先のファイルがすでにあると上書きされるので注意。
- -r:ディレクトリをコピーする。
- -i:上書き前に確認する。
- ln
- find
- chmod
- chown
- change ownerの略
- ファイルの所有者を変更できる。
- ps
- process statusの略
- PIDにプロセスID、CMDに実行中のコマンドが表示される。
- aux:全ユーザーのプロセスを表示する。オプションだけどハイフン不要。
- aが全てのユーザー、uが詳細情報を含める、xがpsコマンドを実行したユーザの全てのプロセスという意味。
- kill
- ジョブやプロセスを終了させる。
- 正確にはkillコマンドはシグナルを送信するもの。
- シグナル
kill 4965
はkill -TERM 4965
が省略されたもの。TERM
のシグナルは終了を指示する。- TERMが効かないプロセスがある場合は
SIGKILL
という強制終了のシグナルがある。安全に終了させず強制終了させるので最終手段のとして使う。
- ジョブを修了させる場合
kill %1
、プロセスを終了させる場合kill 4965
のように書く。
- ジョブやプロセスを終了させる。
Vimの基本操作について
Vimの基本操作について
Vimについて
Linux系OSで、いわゆる黒い画面で使用できるエディタのことです。 マウスが使えないOSでテキストの編集を行う際には使用するのがマストになります。 一方で慣れるとコーディング作業もとても速くできるようになる(らしい)です。 ※筆者はVimを使い始めたばかりで、まだ全然慣れていません。
Vimには以下の表の4つのモード(操作の方式)があります。
モード | 説明 | 他モードからの開始キー |
---|---|---|
ノーマルモード | 最初にVimを起動した際にはこのモード。 カーソルの移動やコピペを行うモードで、普通に文字を入力しても画面に何も入力できません。 |
Esc |
インサートモード | テキストの入力や編集を行うモード | i,I,a,A,o,O等 |
ビジュアルモード | テキストの範囲選択を行えるモード。 矩形選択が強力。 |
v, Shift + v, Ctrl + v |
コマンドラインモード | vim内でコマンドを使用したり、外部のコマンドを呼び出す際に使用するモード。検索や変更、外部ファイルの操作も可能。 | vim内のコマンドは「:"コマンド"」 外部コマンドは「:!"コマンド"」 |
基本のコマンドについて
- 英単語の頭文字で解釈できるコマンドも多いですが、そうでないものも多いです。
- Shiftを押しながらの操作は、「真逆の操作になる」か「小文字の操作よりも大袈裟な操作になる」と解釈すると覚えやすいです。
ノーマルモード
- ノーマルモードへは各モードからEscキーを押すことで移行できます。
カーソル操作
コマンド | 動作 |
---|---|
h, j, k, l | 左、下、上、右の1文字に移動 |
gj, gk | 下、上に1行移動 |
w | 次の単語の先頭に移動 |
e | 単語の末尾に移動 |
b | 前の単語の先頭に移動 |
0 | 行頭に移動 |
$ | 行末に移動 |
gg | ファイルの先頭へ移動 |
G | ファイルの末尾へ移動 |
編集操作
コマンド | 動作 | 何の略か |
---|---|---|
y | 行のコピー | yank |
x | カーソルの文字を削除 | |
dd | カーソル行の削除 | delete |
p | カーソルの下の行にペースト | paste |
P | カーソルの上の行にペースト | |
u | 操作の取り消し | undo |
. | 直前操作の繰り返し |
インサートモードへの移行
コマンド | 動作 | 何の略か |
---|---|---|
i | カーソル位置から入力モードに移行 | insert |
I | 行頭から入力モードに移行 | |
a | カーソル位置の右から入力モードに移行 | |
A | 行末から入力モードに移行 | |
o | カーソルの下に行を挿入し、その行から入力モードに移行 | |
O | カーソルの上に行を挿入し、その行から入力モードに移行 |
ビジュアルモードへの移行
コマンド | 動作 |
---|---|
v | ビジュアルモードへ移行 |
V | カーソルがある行を選択してビジュアルモードへ移行 |
Ctrl + v | 矩形選択のビジュアルモードへ移行 |
コマンドラインモードへの移行
コマンド | 動作 |
---|---|
:wq | テキストを保存しVimを終了 |
:q! | テキストを保存せずにVImを終了 |
:w | テキストの保存 |
:s/old/new/g | カーソル行全てのoldをnewに変換する |
最後に
Vimのコマンドをまとめ直すと、ここに書いたものだけでも全コマンドを使えているわけではないことを自覚しました。 普段からVimを使う→時折使用可能コマンドを振り返る、ということを繰り返すことで徐々にコマンドを覚えていくのだと感じました。
web技術の基本的な用語について
web技術の基本的な単語についてまとめました。
リクエスト、レスポンス
Webアプリケーションをパソコン上で使用するためには、パソコン(クライアント)に対して サーバから情報を取得する必要があります。 クライアント→サーバに対する要求を「リクエスト」、サーバ→クライアントの応答を「レスポンス」と呼びます。
プロトコル
プロトコルとは直訳すると規約のことです。 Webアプリケーションの通信においてのプロトコルは、通信を行う際のルール(規約)のことを指します。 プロトコルがないと、通信をやり取りした際にその通信が何を意味しているのかを互いに読み取ることができません。 そのため、ルールとしてプロトコルを決めて通信を行なっています。 プロトコルの例としては、HTTP、IP、TCP等があります。
ステートフル、ステートレス
ステート(state)は状態という意味を表す英単語です。 Webアプリケーションの通信において以前の通信の状態を保持している場合ステートフル(state+ful)、 保持していない場合ステートレス(state+less)と言います。 FTPはステートフルなプロトコル、HTTPはステートレスなプロトコルです。 ステートフルであると、オーバーヘッド(本来の処理を行うため付随する処理のこと)が大きくなるデメリットがあります。
クッキー
HTTPは、通信手順が簡単でオーバーヘッドが少ないステートレスなプロトコルが必要になっため考案されました。 しかし、HTTP通信を使用した今日のアプリケーションでは状態を保持する必要がある場面が多いです。(ログインの認証など) そこで使用されているのがクッキー(Cookie)です。 HTTPのレスポンスヘッダやリクエストヘッダに「名前=値」の組み合わせの情報を入れて通信を行うことで、 ログイン認証などの状態を管理しています。
ポート番号
通信を受信した際に、通信の中身を見ただけではどのプロトコルで送られてきたものか判別することができません。 そこで、「ポート(直訳すると、港の桟橋)」という考え方を受信時に使うことでプロトコルを判別しています。 プロトコルごとにどのポートで通信を受け取るかを決める、というのがポートの考え方です。 受信時のポート番号をあらかじめ決めておくことで、ポート番号からプロトコルを判断できます。 特に、HTTP等の代表的なプロトコルでは使用するポートを80番にするという取り決めがあります。 この取り決めで決められたポートは「ウェルノウンポート(wel-known ports)」と呼ばれます。 well-known portsがあることで、HTTP等の代表的なプロトコルではの通信ではポート番号を意識することが不要となります。