フロントエンドエンジニアをやっています。
頑張るから読んでほしい。

React Hooksの使い方

このあいだチームのバックエンドエンジニア向けにReact Hooks勉強会を開催しました。

チームのみんなでプロダクトのフロントエンドの底上げをしたくて、React Hooks啓蒙活動です!

改めてReact Hooksについて勉強&まとめることができたのでReact Hooks勉強会の内容をブログにも書いておこうと思います。

これは何?

  • Hooksとは何か?
  • Hooksを使うと何が変わるのか?
  • Hooksの使い方
  • Hooksを書くときのルール

👆についてまとめてます。

対象は

  • Reactは書けるけどHooksって何?
  • Hooksって聞いたことあるけど何がすごいの?
  • Hooks使いたいけど、よく分からないんだよね…

な人向けです。

背景

これから積極的にReact Hooksを使っていきたいなあと思っています。

でもいきなりHooks使おう!ってなっても、 Hooksって何? 使うといいことある? どういいの? 難しいの? って疑問があると思います! なのでチームのみんながHooks良さそう!使ってみようかな!って思えるようなHooksについての入門資料です。

ゴール

Hooks良さそう!使ってみようかな!って気持ちになってチームのみんながHooksで書いたPR作成できる!

Hooksって何?

クラスコンポーネント使わなくても関数コンポーネントでstateなどの機能が使えるようになるやつです!

  • useState
  • useEffect

👆を使うと関数コンポーネントでstateが使えたり、ライフサイクルメソッドっぽいことができます。

関数コンポーネントで書きたい理由

👦: Q. クラスコンポーネントで書けるのにどうして関数コンポーネントを使うの?

👨: A. 👇

  1. クラスComponentと比べてスッキリ、綺麗に書ける
    • 可読性が良くなる
  2. クラス内の this の挙動が難解
  3. 記述が冗長になりがちで、時系列が複雑なライフサイクルメソッドの挙動

これまでのReact

アプリケーションのロジックに関わるコンポーネントはクラスコンポーネント

ロジックをコンポーネント間で再利用するのが難しい

render props や higher-order componentsがあるけど、コンポーネントの再構成が必要だし、ラッパー地獄になりやすいし、可読性が低くてコードを追うのが大変です…

これからのReact

関数コンポーネントで書けるようになる

アプリケーションのロジックに関わるコンポーネント関数コンポーネントで書けるようになります!

ロジックを再利用できるようになる

Custom Hookという独自にhookを作成することを使うとロジックを再利用できるようになります。

再利用できるようになり、コードも綺麗に書けるようになります! ReactのロジックをOSSとして気軽に共有できます!

👦: Q. じゃあ全部Hooksで書いた方がいいの?

👨: A. 新しいコンポーネントはHooksで書いていくのがおすすめ

ref. https://ja.reactjs.org/docs/hooks-faq.html#should-i-use-hooks-classes-or-a-mix-of-both

クラスコンポーネントはいつかなくなるかもしれません… 何年後かのクラスコンポーネント置き換えtaskが辛くならないために新しく作成するコンポーネントは関数コンポーネントで書きたいです!

Hooks使うのは強制ではないです。無理だ!って思ったらクラスコンポーネントでも大丈夫です! でもクラスコンポーネントは将来deprecatedになると思うのでこの機会にぜひ!

Hooks

(チーム内の)プロダクトでよく使いそうなHooksたち

1. useState

関数コンポーネントで状態を持つことができるようになります!=> stateが使える

useStateの基本

const [state, setState] = useState(initialState);

👉 配列の1つ目にstate名(配列が返ってくる)、2つ目に関数(setState)、useStateの中に初期値が入ります。

こんな感じ

const [count, setCount] = useState(0)

useStateの実装

例えば、以下のようなカウンターの実装

クラスコンポーネント

関数コンポーネント hooks

💪+α useStateの中身

const state = useState(0);
console.log(state);

f:id:cidermitaina:20200429144651p:plain

console.logに出してみると以下のようなことが分かります。

  • useStateは配列を返す
  • 初期値が配列の0番目に入ってる
  • 配列の1番目にsetStateの関数っぽいのがある

2. useEffect

関数componentで副作用処理を扱う(DOMの変更、API通信)ことができます。 ライフサイクルメソッドっぽいことができます。

useEffectの基本

useEffect(didUpdate);

👉 didUpdate部分に副作用処理を扱う(DOMの変更、API通信)を書きます。

👦: Q. どのタイミングで実行されるの?

👨: A. 最初の描画時または、再レンダリング時です。

マウント時、再レンダリング時(コンポーネントの全てのstateが変更されるとき)に実行されます。

👦: Q. この値が変更したときだけ実行したい…

👨: A. useEffect の第 2 引数として、この副作用が依存している値の配列を渡します!

useEffect(() => {
    document.title = `クリック数: ${count}回`
    console.log('render')
  }, [count]) // countの値が変更されたときだけ実行されます

👦: Q. マウント時だけ実行したい…

👨: A. useEffect の第 2 引数として、空の配列を渡します!

useEffect(() => {
   mount時の処理
 }, []) // 第2引数に空の配列

useEffectの実装

f:id:cidermitaina:20200429145058g:plain

👆 mount時とcountの値が変更されるとuseEffect内の処理が実行されている

4. useCallback

パフォーマンス向上のためのフックです。 callback関数(イベントハンドラー) をメモ化します。

メモ化

  • プログラムの高速化のための最適化技法の一種
  • 関数の結果を再利用、一時的に保持する

useCallbackの基本

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b], // 依存している値の配列
);

コールバック関数と、依存している値の配列を渡します。 依存配列の要素(a, b)が変化した場合にのみメモ化した値を再計算します。

👦: Q. useCallbackするとどうなるの?

👨: A. 不要に新しく関数インスタンスを作成することを抑制し、不要な再描画を減らすことができます。

不必要なrenderを避けるためにReact.memo(stateやpropsに変更がなければ再レンダリングを行わない)等の参照の同一性を見るよう最適化されたコンポーネントにコールバックを渡す場合に便利です。

👦: Q. useCallbackしないとどうなるの?

👨: A. 全てのcomponentが再renderしてしまい、関数も再生成されてしまいます

useCallbackの実装

useCallbackしない場合 f:id:cidermitaina:20200429153024g:plain

👆 Buttonクリック時fooButtonをクリックするとbarButtonのの関数もrenderされてしまってる

useCallbackした場合 f:id:cidermitaina:20200429152921g:plain

👆 Buttonクリック時fooButtonをクリックするとfooButtonの関数のみ実行

useCallbackはReact.memoと一緒に使うと真の力を発揮するっぽい!

5. useRef

DOMを操作したり、クロージャー内で宣言された値へアクセスできます。 UIの更新に関連しない状態を管理したい場合に使用するイメージです!

useRefの基本

const refContainer = useRef(initialValue);

書き換え可能な値を .current プロパティ内に保持することができる「箱」のようなもの

useRefの実装

DOM操作

クロージャー内で宣言された値へアクセスしたい場合

💪+α 更新前のStateの値を使いたい場面

6. Custom Hooks

独自のhookを自分で作成できます。 独自のhookを作成し、コンポーネントからロジックを抽出することで、ロジックを再利用することができるようになります。

ReactのロジックをOSSとして気軽に共有できるようになったので、探してみるとたくさんOSSのReact Hooksがあります!

👇のOSSを眺めてみるとイメージしやすいかも!

https://nikgraf.github.io/react-hooks/

コードとDEMOは👇の方が探しやすいかも!

https://github.com/streamich/react-use/

(7. useMemo)

プロダクト内では使うことはなさそうなので省略します! 興味ある人は調べてね!

(8. useContext)

プロダクト内では使うことはなさそうなので省略します! 興味ある人は調べてね!

(9. useReducer)

プロダクト内では使うことはなさそうなので省略します! 興味ある人は調べてね!

Hooksのルール

Hooksを書くときに気をつけて欲しいこと&守って欲しいこと

1. Hooksはループや条件分岐の中で呼ぶことはできません!

// これはダメ
const Ng = () => {
  if (condition) {
    useEffect(() => {}, []);
  }
}

// これはOK
const Ok = () => {
  useEffect(() => {
    if (condition) {
      //
    }
  }, []);
}

2. 関数Componentの中からのみ呼べます!

Custom Hooksとして切り出した関数の中では呼ぶことはできるので注意!

3. Custom Hooksを作るときはuseXXXの命名規則に!

この名前にすることでESLint PluginなどでHooksだと認識してくれるようになります。

ESLint Plugin

HooksのESLint Pluginです。

depsの指定忘れを検知してくれます。 基本的には従っておいた方がいいです。

const App = () => {
  const foo = "...";
  const bar = "...";
  const handler = useCallback(() => {
    someFn(foo, bar);
  // fooがdepsに指定されていないのでひっかかる
  }, [bar]);
}

意図的にやっている場合やESLint Pluginが誤検知してる場合は、eslint-disableのコメントで無効にできます。

https://eslint.org/docs/user-guide/configuring#disabling-rules-with-inline-comments

まとめ

チームのプロダクトで良く使いそうなReact Hooksについてまとめてみました!

このReact Hooksについての内容はチームのみんなでプロダクトのフロントエンドを良くしたいなあと思って作ったものです。

React Hooks使いたいけどなかなか…って思ってた人や、プロダクトのフロントエンドを良くしたいなあって人の参考になれば嬉しいです。





参考

HMRでファイルを変更してからブラウザで変更が反映されるまで

HMR(Hot Module Replacement)ってみなさん使ってますか?

HMRは、webpackの提供する仕組みで、ページの再読み込み無しで、モジュールの交換・追加・削除をアプリケーションの動作中にブラウザに適用してくれる開発ツールです。

ブラウザをリロードしなくても変更したモジュールだけが更新されるし、開発の時間が節約できて便利ですよね!

最近HMRってどうして変更したモジュールだけが更新されるのかなあって考えたことがあったのでまとめてみました。

HMRの仕組み

HMRでファイルを変更してからブラウザで変更が反映されるまでの流れは以下のような仕組みになっています。

f:id:cidermitaina:20200406002555p:plain

f:id:cidermitaina:20200406103524p:plain Webpackのコア、プラグインライブラリ f:id:cidermitaina:20200406103749p:plain Webpack-dev-server関連のライブラリ f:id:cidermitaina:20200406103927p:plain HMRライブラリ(react-hot-loader、style-loader等) f:id:cidermitaina:20200406104139p:plain 変更したファイル(js, css等) f:id:cidermitaina:20200406104022p:plain アプリ(ブラウザ上で確認できるもの)

1~2. ファイルの変更

webpackはファイルの変更を監視しています。 ファイルを変更すると、Webpackは変更を取得し、HotModuleReplacementPluginに通知します。

3. manifestとchunkの作成

WebpackはHotModuleReplacementPluginを使用して manifestファイル(変更されたモジュールのリストを含むJSON)と updated chunkファイル(実際の変更情報を含むjs)を生成します。

4. Webpack-dev-serverに変更を通知

WebpackはWebpack-dev-serverに変更を通知します。

5. Webpack-dev-server/clientに変更を通知

Webpack-dev-serverは、WebSocketを介して「無効な」通知を送信することで、Webpack-dev-server/clientに変更を通知します。

Webpack-dev-server/clientは、アプリが最初にhot/dev-serverライブラリに読み込まれたときに取得した初期ハッシュ(例:c6202ec89ecd4e669b46)をWebpack-dev-serverに送信します。

Webpack-dev-server/clientとは?

WebSocketを介してブラウザーで実行されているJSファイル。
Webpack-dev-server関連のライブラリ。

6~8. manifestファイルのダウンロード

Webpack-dev-server/clientはhot/dev-serverに変更を通知し、hot/dev-serverはWebpackによって挿入されたJSONP runtimeを呼び出して、3で生成したmanifestファイルをダウンロードします。

manifestファイルには、chunkに関する詳細が含まれています。例えば、ファイル名はc6202ec89ecd4e669b46.hot-update.jsonで、中身は以下のようになります。

{h: "0355e4eec902c32b2d0b", c: {0: true}}

9. updateファイルのダウンロード

JSONP runtimeはmanifestファイル内に含まれる情報を使用して、すべてのupdateファイル(js)をダウンロードします。

変更に関する情報が含まれていて、DOMに追加されて実行されます。

updateファイル(js)の中身は以下のような感じ。

webpackHotUpdate(0,{

/***/ 116:
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react__ = __webpack_require__(85);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_react___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_react__);

//# sourceMappingURL=0.c6202ec89ecd4e669b46.hot-update.js.map

10. HMR runtimeの呼び出し

updateファイルは、モジュールID(上記の例ではmodule id 116)と変更内容を使用してHMR runtimeを呼び出します。

11. loaderにを変更を委任

HMR runtime自体は、変更を適用する方法を知らないので、Reactであればreact-hot-loader、cssであればstyle-loaderなどの対応するloaderにを変更を適用してもらうようにお願いします。

12. モジュールの更新

変更の適用に問題(構文エラー等)がない場合は、モジュールが更新されます。 ここでやっとモジュールファイルを変更してブラウザ上で変更の確認することができるのです。

もし問題があれば、hot/dev-serverにエラーが通知されます。

HMRの変更を実際に見てみる

次は、実際にHMRを使うとブラウザではどのような動きになっているのか見ていきます。

さくっと動きを確認したいのでReact Hot Loaderのboilerplateを使って実際にHMRで変更したときの流れを見てみることにします。

1. Webpack-dev-serverを起動

まずは、以下からReact Hot Loaderのboilerplateを落としてきてWebpack-dev-serverを立ち上げます。

github.com

Webpack-dev-serverを起動するとコンソール上に以下のようなログが表示されます。

f:id:cidermitaina:20200406005855p:plain

[HMR]はWebpack/hot/dev-serverのログ

[WDS]はWebpack-dev-serverのログ

になります。

2. ファイルを変更

src/containers/Root.jsを変更してみます。

とりあえずHello React Hot Loader!Hello World!に変更してみました。

import React from "react";

const Root = () => <div>Hello World!</div>;

export default Root;

3. サーバーとクライアントでのやり取り

ファイルの変更後、dev toolのNetworkタブのWebSocket欄を確認するとハッシュを送信したりしてることが分かります。 webpack-dev-serverは、WebSocketを介してファイルの変更についてクライアントと常に通信しているみたいです。

f:id:cidermitaina:20200406010904p:plain

4. 変更をアップロード

次にdev toolのNetworkタブ欄を確認すると、webSocketを介して得た現在のハッシュ(001efdfaf0c0e6150d7f)を使用して、manifestファイル(001efdfaf0c0e6150d7f.hot-update.json)をダウンロードしていることが分かります。 また、manifestファイル内に含まれる情報を使用して、updadeファイル(0.001efdfaf0c0e6150d7f.hot-update.js)をダウンロードしていることも分かります。

manifestファイル(001efdfaf0c0e6150d7f.hot-update.json)の内容は以下。

f:id:cidermitaina:20200406011556p:plain

5. 変更内容を更新

updadeファイル(0.001efdfaf0c0e6150d7f.hot-update.js)を確認するとファイル内にwebpackHotUpdate関数があり、 このwebpackHotUpdate関数を呼び出すことでHMR runtimeに変更内容が渡されます。

HMR runtimeは、この変更内容をReact Hot Loaderに渡し、変更内容が更新され変更内容がブラウザで確認することができます。

updadeファイル(0.001efdfaf0c0e6150d7f.hot-update.js)f:id:cidermitaina:20200406012135p:plain

まとめ

普段何気なく使ってるHMRですが、改めてHMRって何だろうって考えたときにリロードしなくても変更したモジュールだけ変更できるのってすごくない…!! って思ったのがきっかけで仕組みを調べてみました。

仕組みを少し理解できたのでWebpackの設定周りが理解しやすくなった気がしています。



参考

Hot Module Replacement | webpack

Webpack & The Hot Module Replacement - rajaraodv - Medium

2019-09 → 2020-03

仕事について

去年の9月にSmartHRのフロントエンドエンジニアとして転職をしました。 3月で入社して6ヶ月になるので、少し振り返ってみようかなあっと思って書いています。

入社してからの3ヶ月

はじめてのお仕事は、比較的小さいアプリのフロントエンドリニューアルのお仕事。

既存のrailsアプリにReact, TypeScriptを入れて、作り直しました。

私にとっては、はじめてのReact, TypeScriptでとても刺激のある3ヶ月でした。

やったことは、

既存railsアプリにWebpackを入れてフロントエンドを切り分けた

既存のRailsアプリにReact, TypeScirptを入れてフロントエンドリニューアルをする際に、最初に悩んだのが、 Reactを入れる、動く環境を作るためにはどうしよう?

でした。  

  1. webpackerをいれる
  2. 自分でwebpackを用意する
  3. 上記以外の何か別の何かの方法...?

上記3つの方法を検討していたのですが、

  • フロント部分の細かな設定がしたい
  • webpackerだと
    • 細かい設定が大変
    • webpackerの学習コストやwebpackのバージョンアップについていけないことが辛い
  • 他のプロダクトと設定を統一したい

という理由から、自分でwebpackを用意し、フロントエンドを切り分けることにしました。

React, TypeScriptで作り直す

はじめてのReact, TypeScriptだったので、慣れるまではとても時間がかかりました。。。(しんどかった…)

苦労したところは、はじめてやることなので時間がかかるでした。

なので、

↑の本を読んだり、先輩に教えて貰ったり、ちょっと早めに出社して勉強したりしながらやっていました。

UIのコンポーネント

もともとスタイルははscssで書かれていたのですが、フロントエンドリニューアルにあたって、Styled Componentsを使用することにしました。

Reactはコンポーネント・ベースでUI開発することに特化したJavaScriptライブラリなので、個人的にはコンポーネント単位でcssを管理したく、コンポーネント単位でスコープが生成されるStyled Componentsで書き直すことにしました。

他のプロダクトもStyled Componentsなので、統一したかったっていうのも理由のひとつです。

UIのコンポーネント設計部分はAtomic Designを採用しました。 フロントエンドリニューアルするプロダクトは開発人数が少ないため、UI設計の共通認識が持ちやすそう、またメンテナンスしやすいUI開発がしたいと思い採用しました。

こちらもはじめてのStyled Components、Atomic Designだったので、

↑のdocsを読んだり、Atomic Designの本を読んだりしてました。

Ruby on Rails

フロントエンドのリニューアルなので、あんまりバックエンド部分は触ることはなかったのですが、 どうしても修正しないといけない箇所があったりで、コードを読んだり、修正したりしてました。

railsはあんまり得意ではなく… 事前にその話をしていたので、先輩がすぐに助けてくれたり、丁寧に教えてくれたりしたおかげで少しだけrailsのこと理解できた気がします。(たぶん)

入社してからの4ヶ月目~今

今年に入ってから、新しいチームに配属になりました。

以前やっていたプロダクトよりも大きいプロダクトで技術スタックはRails, React, TypeScript、 そして半年ほど専任のフロントエンドエンジニアがいなかったチームです。

フロントエンドエンジニアの人数が少ないので、チームのフロントエンドエンジニアは私一人だけです。

私一人で大丈夫かな、私で大丈夫なのかなって不安がたくさんあったのですが、 チームのみんなは、困ってるとすぐに助けてくれたり、いっしょに悩んでくれたり、とても心強く、楽しく開発できています。

今のチームに入ってからやったこと&やっていることは、

tslintをやめた

TSLintは現在非推奨になっています。

なので、TSLintはやめて、eslintに変更しました。

既存のUIをSmartHR UIに変更

SmartHRには共通のコンポーネントライブラリSmartHR UIがあります。 また、SmartHRにはたくさんのプロダクトがあり、プロダクトによっては少しUIが違っていたり、カラーが違っていたりしています。 プロダクト間でのUIの統一をし、多くの人に使いやすいと思ってもらいたいので、既存のUIをSmartHR UIに変更しています。

(まだ途中で、置き換え作業中です。)

フロントエンドの問題点の洗い出し

しばらく専任のフロントエンドがいないプロダクトだったので、 フロントエンド部分のコードを良くしていきたい、底上げをしたいと思っています。

フロントエンドのコードに関して

  • どんな問題点、課題があるのか、
  • 将来的にどうしたいのか

を洗い出しました。

↑を踏まえてフロントエンドの技術顧問の方に相談したり、先輩に相談したり、 チームのみんなにも共有して協力してもらったりしています。

jsのts化

もともとjsで書かれていたのですが、以前チームにいたフロントエンドの先輩が半分以上TypeScriptにしてくれていました。

ですが、まだjs部分が残っています。。。

堅牢性をあげたいので、早くts化を終わらせたいなあと思っているので、ちょっとずつTypeScriptにしようと頑張っています。

ビルド周りの改善

以下は、私がやったことではなく技術顧問の方がやってくださりました。

以前はTypeScriptのコンパイル部分をawesome-typescript-loaderを使用していたのですが、ts-loaderに変更しました。 変更することで、コンパイルの速度が速くなりました。

また、ESModulesのままwebpackに渡すようにしてTreeShakingを有効にしました。

これで本番ビルドのファイルサイズが削減されました。

// tsconfig.json
{ 
  "compilerOptions": {
    "target": "es5",
    "module": "esnext",
    "sourceMap": true,
    ...
    ...
    ...

TypeScriptコードのimport文とexport文がコンパイラによってCommonJSとして変換されるため、Tree Shakingの効果を得るためには明示的にES Modulesをコンパイルオプションで指定するみたいです。

上記2つは、技術顧問の方にPRを出していただいたのですが、私自身ビルド周りが詳しくなく…勉強になりました!

振り返り

半年を振り返ると、はじめてなことばかりで大変だったけど、出来ることが増えて嬉しい気持ちとやりがいがあります。

今やってるプロダクトのフロントエンドが良くなっていくのを感じる度に、私のフロントエンド力も一緒に成長している気持ちになっています。

入社して半年がたち、このままこのプロダクトと一緒に成長していけたらなあ、前職、現職含めお世話になった人にお仕事で恩返しができたらなあ、と日々思いながらお仕事をしています。

2019年振り返り

2019年を

  • WORK
  • STYDY
  • PRODUCT
  • BLOG
  • BOOK
  • MUSIC

で振り返ります。

WORK

お仕事は上手くまとめられなかったので月ごとに簡単にまとめます。

1月

悩み事が多かった気がする。

2月

辛いことがありました。
辛いこともあったけど、嬉しい言葉をかけて貰えたのも2月でした。

3月

UI/UXチームは2人で開発してたけど、webチームとwebメッセージ開発を始める。
先輩と朝勉強をはじめた。
先輩との勉強で一番印象に残ってるのは、
”webはHippy”

4月

きちんとテストすることの大切さを学んだ4月。
web-sdkのリリースを先輩といっしょにやった。
朝活も続いてる。

5月

チーム解体。スクラムの導入。Lessの勉強。
環境の変化に対応するのに大変だったけど、チームのメンバーは最高だった。

6月

sprint planningでのTaskの分割が上手くできない。分からない。
サーバーサイドもインフラもフロントエンドも何も分からない…

7月

頑張れなかった。
会社を辞めた。
何もかも自信がなくなった。
憧れてるエンジニアの人と面談をした。誕生日の日だった。
ブログを読んでくれたり、頑張ってるのを見てくれてた人がいるんだと嬉しい気持ちになった。
もう少しだけ頑張ろうと思った。

8月

ゆっくりすることにした。
音楽を聴いたり、花を飾ったり、本を読んだり、ご飯をちゃんと作るようにした。
夕方よく散歩をした。時々見かける子供とお母さんの会話をぼんやり聞いたりした。

9月

転職した。
はじめて設計含めてフロントエンド開発することになった。
ReactもTypeScriptもはじめてやる。
既存railsアプリにreactを導入した。
webpackerいれるか考えたりした。(いれなかった)

10月

サーバー側のデータをフロントでどうやって取得しようか悩んだりした。
form送信できない…CSRFトークンとは?ってなった。
Smart HR UIにselect boxコンポーネントのPRを出した。嬉しい。

11月

入社後、なんとなくReactとTypeScriptを先輩のコードを参考に書いてたけど、
これじゃだめだ!と思って、朝活を始める。
TypeScriptの勉強を毎日することにした。
少しずつ会社の人に慣れてきた。

12月

先輩が設計に関してPRを出してくれた。とても勉強になった。
リリースまで12月までにできなかったけど作りきった。
自信になった。
少しずつ会社の人に心を開いてきた。

STUDY

今年は、ブラウザについて勉強しました。
もともと仕組みが分からないともやもやして先に進めない性格なので、
ブラウザについて勉強したのは、とても良い経験になったように思います。

ブラウザの仕組みで一番好きなのはParse(構文解析)の部分ですって話を先輩にすると the-super-tiny-compilerを教えてくれたので、コードリーディングしたり写経したりしました。

あとは、テスト技法を少しだけ学んでみたり、React、TypeScriptに挑戦してみたり、Atomic Designについても勉強してみたり。です。

来年は、興味のある分野についてもっと勉強していき、自分の強みを見つけることができたら、なんて思ってます。

PRODUCT

the-super-tiny-compiler.jsを写経したものをブラウザ上で使えるように作ってみたり、
ReactとTypeScriptに慣れたいので、練習のためにReactとTypeScriptでTEA PAGEを作ったり、ポートフォリオを作り直したりしました。

Reduxを使ったアプリを作りたいなあと思ってるのですが、サーバー構築に対して苦手意識があるので、来年はその辺りも含めて何か作ってみたいです。

BLOG

12本書きました。(その内1本は音楽について)

以下の3つは書いてて楽しかったブログ。

今年は、Web、ブラウザについての記事を多く書きました。 去年は15本書いているのですが、内容的には濃い内容を今年は書いている気がするので、来年もこの調子でアウトプットしていきたいです。

BOOK

技術書

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)

  • 作者:山本 陽平
  • 発売日: 2010/04/08
  • メディア: 単行本(ソフトカバー)

Webフロントエンド ハイパフォーマンス チューニング

Webフロントエンド ハイパフォーマンス チューニング

  • 作者:久保田 光則
  • 発売日: 2017/05/26
  • メディア: 単行本(ソフトカバー)

Atomic Design ~堅牢で使いやすいUIを効率良く設計する

Atomic Design ~堅牢で使いやすいUIを効率良く設計する

  • 作者:五藤 佑典
  • 発売日: 2018/04/25
  • メディア: 単行本(ソフトカバー)

実践TypeScript ~	BFFとNext.js&Nuxt.jsの型定義~

実践TypeScript ~ BFFとNext.js&Nuxt.jsの型定義~

  • 作者:吉井 健文
  • 発売日: 2019/06/26
  • メディア: 単行本(ソフトカバー)

booth.pm

小説

トニオ・クレエゲル (岩波文庫)

トニオ・クレエゲル (岩波文庫)

メルヒェン (新潮文庫)

メルヒェン (新潮文庫)

  • 作者:ヘッセ
  • 発売日: 1973/07/03
  • メディア: 文庫

星の王子さま (新潮文庫)

星の王子さま (新潮文庫)

第七官界彷徨 (河出文庫)

第七官界彷徨 (河出文庫)

  • 作者:尾崎 翠
  • 発売日: 2009/07/03
  • メディア: 文庫

道をひらく

道をひらく

買ったけど読んでない&読みたい

Real World HTTP ―歴史とコードに学ぶインターネットとウェブ技術

Real World HTTP ―歴史とコードに学ぶインターネットとウェブ技術

  • 作者:渋川 よしき
  • 発売日: 2017/06/14
  • メディア: 単行本(ソフトカバー)

「実践ドメイン駆動設計」から学ぶDDDの実装入門 (CodeZine Digital First)

「実践ドメイン駆動設計」から学ぶDDDの実装入門 (CodeZine Digital First)

  • 作者:青木 淳夫
  • 発売日: 2019/05/31
  • メディア: オンデマンド (ペーパーバック)

夜と霧 新版

夜と霧 新版

かげろうの日記遺文 (講談社文芸文庫)

かげろうの日記遺文 (講談社文芸文庫)

今年はけっこう本を読んだ気がします。
就活してたときに、説明会でもらった道をひらくって本、改めて読むととても滲みました。

ヘッセのアヤメという短編が今年の一番です。

MUSIC

open.spotify.com

open.spotify.com

open.spotify.com

open.spotify.com

www.youtube.com

www.youtube.com

今年はThe World Will Tear Us Apartという京都のバンドのアルバムが冬にリリースされました。
大学生の頃からずっと待っていたのでなんだか感慨深いです。

個人的にDIIVの新しいアルバムが衝撃でした。(良い意味で)

TO 2020

今年は本当に辛かったです。
辛かった分、得たことも多かった一年のように思います。

辛かったこと、得たこともしっかり受け止めて来年もまた少しずつ頑張れたらいいなあ、と思っています。

来年は自分の得意領域を見つけ、深堀りして行ったり、成長を実感できるような年にしていきたいです。

では、2020年も宜しくお願いします。

f:id:cidermitaina:20191229172932p:plain

実践 TypeScriptの読書MEMO1

最近、実践 TypeScriptを読んでいるので読書メモです。

実践TypeScript ~	BFFとNext.js&Nuxt.jsの型定義~

実践TypeScript ~ BFFとNext.js&Nuxt.jsの型定義~

  • 作者:吉井 健文
  • 発売日: 2019/06/26
  • メディア: 単行本(ソフトカバー)

私の知らなかったことをたくさん書いてます。

どんな本

  • TypeScript特有の知識を体系的に学ぶための1冊
    • 集中してTypeScriptの型定義を深く学べる
  • 1部は基礎知識、2部は理解を深める
  • TypeScriptを導入するメリット
    • 分割されたモジュール同士の依存関係を担保する
    • 型システムが、バックエンドからフロントエンドの末端のviewまで一環して不整合ないデータの橋渡しを実現する

目的

  • TypeScriptの型定義きちんと理解したい
    • 型定義ははじめてなので…
  • 最終的にTypeScriptを実践的に使えるようになりたい
  • 先輩のTypeScriptのコードをちゃんと理解できるようになりたい
  • 4章5章をちゃんと読んでTypeScriptのコンパイルエラーの解決慣れしたい

1. 開発環境と設定

1-1. tsconfig.json

TypeScriptコンパイラーの設定ファイル。 tsc --initで作成

tsconfig.json

{
  // teconfig.jsonの初期値
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true
}

target

トランスパイル後のECMAScriptのターゲットバージョン。

  • es5
  • es2015
  • esnext

module

コード生成モジュールを指定

  • commonjs
  • amd
    • define()に配列でモジュール名を指定する

strict

型の厳密さを一括して指定

一括で有効になるのは以下の指定

  • noImplicitAny
  • noImplicitThis
  • alwaysStrict
  • strictBindCallApply
  • strictNullChecks
  • strictFunctionTypes
  • strictPropertyInitialization

1-2. 型宣言ファイルの出力

関数定義などの型を通達するために、型宣言ファイル(.d.ts)が利用できる

.d.tsいつ使うんだろう🤔

  • 型情報が消えしまう
  • .d.tsは型定義が分かる
  • JavaScriptで書かれたライブラリには型情報がない…
  • ライブラリ等で使うときは型定義ファイルがあれば、みんなが幸せになれる

1-3. ライブラリの型定義を利用する

npmで配信されているライブラリには、TypeScriptの型定義が存在するものとしないものがある。

DefinitelyTyped

TypeScript型定義ファイル(dts)を用意していないJSライブラリのための型定義ファイル集 @typesで始まるパッケージ

2. TypeScriptの基礎

TypeScriptのもっとも基本的な用語の呼称・利用方法についての章。

2-1. JavaScriptの課題

1. 引数に数値として扱うことのできない値を渡してしまいNaNが表示されてしまう

  • 引数を型注釈で制約する
function expo2(amout: number){
  return amout ** 2
}

2. 計算の途中、数値が文字列に変換されてしまいNaNが返ってくる

  • 関数戻り値に型注釈(アノテーション)を付与。明示的に戻り値を制約。型注釈と定義内容に型不整合がある場合はコンパイルエラーを得ることができる。
function fee(amount): number {
    return amount * 1.4
}

2-2. 基本の型

(私の知らなかった型をまとめてます。)

  • tuple型
    • 固定数の要素がわかっている配列を表現できる
    • 配列の要素ごとに型が違うデータ型が定義できる。
      • let x: [string, number]
  • any型
    • 型の不明な変数を扱うことがある場合に使用することで型チェックを無効にし、コンパイルを通過させる
    • TypeScriptの恩恵を受けることはできないので、できる限りany型が現れないコードを書き、型安全なプロジェクトを目指す。
  • unknown型
    • any型に似ているが、型安全なanyを表したいときに利用する
  • void型
    • any型の反対のようなもの。型が全くないことを表す。
    • 一般に、値を返さない関数の戻り値として利用
  • never型
    • 発生し得ない値の型を表す
    • 返り値が無いことを表すvoid型とは異なり、そもそも関数が正常に終了して値が返ってくるということがあり得ない場合
function func(): never {
   throw new Error('Hi');
 }
 const result: never = func();
  • object型
    • 非プリミティブ型
    • {}を使った型表現ではエラーを得ることができない

2-3. 高度な型

  • Intersection Types
    • 複数の型を一つに結合する
  • Union Types
    • Union Types(共用体)は複数の型のうち一つの型が成立することを示している。
      • let value: boolean | number | string
        • array型を含む要素をUnion Typesにする場合
      • let numberOrString: (number | string)[]
        • Nullable型を表現できる
      • let nullableString: string | null
  • Literal Type
    • String Literal Types
    • 文字列に必要な正確な値を指定できる
    • let users: 'Taro' | 'Jiro'| 'Hanako' (Union Typesと併用)
    • Numeric Literal Types(数値リテラル)
    • Boolean Literal Types(真偽値リテラル)

2-5. アサーション

任意の型に変換することができる。

アサーションは2種類の書き方がある。

  • <変換したい型>値
  • 値 as 変換したい型
let text: any = "this is a string";
let textLength: number = (<string>text).length;
let text: any = "this is a string";
let textLength: number = (text as string).length;

↑ 文字列の文字数を取得するために string に変換して length を呼び出している

<>ではJSXタグとの区別が曖昧になるため、非推奨

2-6. 列挙型

enumを使用すると、列挙型を定義できる。 列挙している属性以外が入ってくると怒ってくれる

3. TypeScriptの型安全

バグを減らすことはTypeScriptを導入する大きな理由の一つであり、

TypeScriptを使いこなすようになるほど、絞り込むという作業がバグを減らす上でいかに重要な作業かということに気づくらしい。

3-1. 制約による型安全

  • アノテーションを用いると、引数や変数定義において、誤った値の代入を防げる。
  • null, undefined
    • 早期return(ガード節、Type Guard)
  • Weak Type
    • すべてのプロパティがオプショナルな型

3-2. 抽象度による型安全

  • 抽象的な型は広く値を受け付けることができる
  • 詳細な型は担保された制約の下で処理を安全に展開できる
  • 抽象的な型・詳細な型がどのようなものであるかを理解し、抽象度をコントロールすることが必要
  • キャスト
    • 変数の型を別の型へ変換すること
  • ダウンキャスト
    • 抽象的な型から詳細な型を付与すること(互換性があるときのみ可能、互換性がない場合は成立しない)
  • アップキャスト
    • 抽象度をあげる
  • インデックスシグネチャ
    • 任意のプロパティを動的に追加することが可能
  • 危険な型の付与
    • Non-null assertion
    • double assertion

4. TypeScriptの型システム

バグを減らすことはTypeScriptを導入する大きな理由の一つ。

TypeScriptを使いこなすようになるほど、絞り込むという作業がバグを減らす上でいかに重要な作業かということに気づくらしい。

4-1. 型の互換性

any型の互換性

  • どんな型にも宣言・代入できる。
  • any型は、どのように扱おうとも危険な型

unknown型の互換性

  • unknown型は、どんな型の値も受け入れることができるTopTypeであり、型の中でもっとも抽象的な型。
    • any型とは異なり安全に扱うことができる型
  • unknown型の値はどんな値なのか分からないため、できることが制限されている。  - (任意の値を代入できる点はany型と同じ、型アサーション等が無いと利用できない。)

{}型の互換性

  • 型に互換性がありため、いずれもコンパイルエラーにはならない。
  • {}という型はオブジェクト以外も受け付けてしまう。(ただし、undefinedとnullはだめ)
  • プリミティブ型は{}型のサブタイプ

5. TypeScriptの高度な型

Generics

  • Genericsを用いると、型の決定を遅延できる。
  • Genericsが割り当てられた型定義に対し、< >の内側に型指定をすることで、導かれる型推論を可変にできる。

基本的な付与

  • Genericsを利用する型を宣言する場合、型名称に続いて<T>のようにT型をエイリアスとして指定する。
  • 慣習的にT, U, Kなどの型エイリアス名称が利用されることが多い。

Genericsを利用する型の宣言

interface Box<T> {
    value: T
}
const box0: Box = { value: 'test' } // Error! Genericsを指定していない
const box1: Box<string> = { value: 'test' }
const box2: Box<number> = { value: 'test' }// Error! Number型ではない





実践TypeScriptの読書MEMO2に続きます。

2019 上半期 聴いたもの

2019年の上半期によく聴いた、印象的だった音楽について。

まず最初に、この半年に聴いた新譜の中でもこれはヤバすぎるな… と思ったのがいくつかあるので以下に。

youtu.be

open.spotify.com

ノルウェー出身19歳の宅録女子らしい。 dead girl in the poolという曲のタイトルで狂気的な印象を受けたけど、

「なんとも言えない不安な気持ちとか、自分は誰であるかというアイデンティティの揺らぎとか、そういった気持ちに根ざした恐怖感を表現したかった」

ということらしい。



open.spotify.com

知り合いに教えてもらった。 甘ったるい感じに歌う声が好きです。



open.spotify.com www.youtube.com

ここ最近で一番衝撃的な新譜でした。

言葉とサウンド(メロディ?音?)が究極に美しいです。 Everythingは特に綺麗。



open.spotify.com

高揚感に溢れます。



open.spotify.com

高熱でぼんやりしてるときって夢でよく京都での大学時代の夢を見るなあと思いながら聴いています。



最近聴いて印象的だったもの。

open.spotify.com

open.spotify.com

open.spotify.com

open.spotify.com

open.spotify.com

open.spotify.com



音楽は相変わらず毎日聴いているし、何か聴いていないときの方が少ないのではないかってくらい聴いています。

自分から何か探すことは減ってきていて、Spotifyが勧めてくれるおすすめの音楽を聴くことが多くなったかもしれないです。 あとは、今まで好きだったバンドの新譜とか、そういうものばかりを聴くことが多かったです。



2019年ではないけど、ここ最近で読んだ本、漫画についても。

草の花 (新潮文庫)

草の花 (新潮文庫)

トニオ・クレエゲル (岩波文庫)

トニオ・クレエゲル (岩波文庫)

メルヒェン (新潮文庫)

メルヒェン (新潮文庫)

星の王子さま (新潮文庫)

星の王子さま (新潮文庫)

風立ちぬ・美しい村 (新潮文庫)

風立ちぬ・美しい村 (新潮文庫)

バースデイ・ストーリーズ (村上春樹翻訳ライブラリー)

バースデイ・ストーリーズ (村上春樹翻訳ライブラリー)

あんまり、楽しい小説は読んでいなくて、言葉の綺麗な小説を探して読んでいました。

ヘッセはなぜか苦手意識があったけど、アヤメは本当に美しくて綺麗な話で... 好きな話のひとつになりました。

あとはスラムダンクを読みました。





ここ最近はこんな感じです。

なんだか疲れているような感じで、いろいろと立ち止まってみるのもいいのかもしれない。と思ったりする日々です。 ゆっくり音楽を聴いたり、ご飯を丁寧に作ってみたり、花を生けたり、好きなお茶を選んで淹れてみたり...

夏休みのつもりでのんびりしています。

夏休みが終わったら、また頑張れるだろうか。



アドレスバーにURLを打ち込んでページが表示されるまで

ブラウザを立ち上げてアドレスバーにURLを打ち込んでEnter押してからページが表示されるまでに (裏側で) 何が起こっているかわかる限り説明してみてください。

という問題に15分何も見ずに考えてみるというのを以前(2月くらい?)やってみたので、そのMEMOです。

予想

何もブラウザに関して勉強せず、15分考えてみた予想(結果)は以下です。 (すごくざっくりしてるので恥ずかしい...)

  • アドレスバーに打ち込んだURLがサーバーに送られる
  • サーバーがURLを受け取る
  • サーバーがデータベース?データサーバー?にURLの情報を探しにいく
  • 見つかったらサーバーがクライアント側にその情報を返す(その情報ってなんだろ?html、css、jsとか?)
  • クライアント側、ブラウザが受け取り、htmlやcssなどをレンダリングする
  • 表示

勉強後

あまりにも書けなかったことがショックだったので、

Webフロントエンド ハイパフォーマンス チューニング

を読んでブラウザのレンダリングの仕組みについて学んでみました。

勉強後、同じように15分何も見ずに考えてみた結果が以下です。

  • アドレスバーにURLを打ち込む
  • ホスト名をIPアドレスに変換した上でネットワークプロトコルを介して必要なリソースを取得
    • リソース→HTML、css、js、画像など
  • まずはHTMLから読み込み、DOMツリーの構築をする
  • DOMツリーの構築 (DOMツリーとはレンダリングエンジンが解釈できるようしたもの)
  • DOMツリーの構築中にcssやjs、画像の参照があれば読み込む
  • cssをもとにCSSOMツリーの構築
  • jsファイルをもとに字句解析
  • トークン化
  • 抽象構文木
  • コンパイル
    • javascriptエンジンが解釈できるように変換
    • よく使われているのがJIT
  • javascriptの実行
    • CPU上で実行
  • DOMツリーをもとにレイアウトツリー構築構築をする
  • スタイルの計算
    • どのDOMにどのcssプロパティが当たるか計算
    • cssの詳細度の計算
  • レイアウト
  • レイアウト情報の計算をしレイアウトの作成(設計図みたいなもの)
    • レイアウト情報→margin,paddingなどの位置
  • ペインティング
    • 2dグラフィックエンジン向けにRender Treeをもとに命令を作成
  • ラスタライズ
    • レイヤーごとに描画
    • レイヤーはposition ,opacity,z-indexごとに
  • レイヤーの合成
    • できたレイヤーを合成
  • ブラウザに表示される

感想

最初は、

ブラウザを立ち上げてアドレスバーにURLを打ち込んでEnter押してからページが表示されるまでに (裏側で) 何が起こっているかわかる限り説明してみてください。

の問いに対してあまり書けなかったのですが、ブラウザのレンダリングの仕組みの勉強後、3倍くらいの量で書くことができました! ブラウザに関する知識が身についた感触があります。

ブラウザに対して興味を持ったので、今後はネットワークやコンパイル、レイアウト、ラスタライズ等の自分の興味を持った分野に対して深掘りしていき、この問いに対しては定期的に考えてみたいなあと思っています。 (来年も同じ問いに対して考えて、書ける量を増やしていけたらなあ...)