ryoのぼやき

技術についての学習内容のまとめです。

【2021年3月】 1st week review

振り返り

読本

  • 起業のファイナンス
    【進捗】
    ~42%
    【感想】
    4章は企業価値についての考え方が書かれていた。
    見積もり方や、事業価値、株価との関係性がためになった。



  • リーダシップの旅
    【進捗】
    ~30%
    【感想】
    リーダーとマネジメントの違いの説明の1つとして、

リーダーは「見えないもの」を見て、あるいは見ようとして、新しい世界をつくり出すのに対し、マネジャーは「見えるもの」を分析し、

とあったのが、興味深かった。
マネジャーとリーダーを同じものと捉えたままこれらを兼務してしまうと、
どちらかの役割しか果たしていない状態に満足してしまいそうだと思った。



  • 初めてのGraphQL
    【進捗】
    ~20%?
    【感想】
    一度読んだ本だったけど、最近仕事で使うようになったので再度読み直し中。
    GraphQLのメリット、RESTとの違いなどを改めて認識。



    開発

    ・【Vue.js】Composition API の reactive の喪失
    なかなか完全な理解ができず、何度も詰まってその度に質問してる気がする。
    reactive() でobject をreactiveなものにできるけど、取り出した値はreactiveではなくなる。
    更新などによってもreactiveが喪失する。喪失したものは computedを使うなどしてRefishにすればreactive になる。

    ・【TypeScript】Utility Type もろもろ
    ライブラリの型定義を読んで理解するのにいまだに結構時間がかかる。
    Utility Type は何度も目にして、逐一調べる回数が減ってきた気がする。

    ・【Vue.js】数値3桁区切り用ライブラリ開発
    途中まで自分で書いてたけど、AutoNumericなるライブラリがあるのを知って、ラップしたものに切り替えた。
    切り出してとりあえず公開。
    GitHub - ryo-gk/vue-thousand-separator


    雑記

    1日水2リットル飲む習慣を始めて1カ月がたった。
    肌の乾燥が少し減ったような気がする一方、トイレの頻度がすごく多くなった。
    MTG前にトイレ行く習慣も一緒についたと思う。

2020年振り返り

はじめに

いろいろな人に振り返り記事を見て、自分も1年の区切りとして2020年の振り返りをしてみました。 仕事、プライベートのそれぞれについて、技術に関連する部分を中心に振り返っていきます。

2020年振り返り

仕事

仕事では、チームが変わったこともあり使用する技術スタックも少し変わりました。 2019年は Java を主に使っていて、フロントエンドは jQuery が主でしたが、 サーバーサイドは、Kotlinと TypeScriptを、フロントエンドは Vue.js をフレームワークとして使うようになりました。 また、これまで使うことがなかった Spring FW を使うようになり、これまでなんとなくで理解していた DI の概念などを改めてきちんと理解するきっかけとなりました。 フロントエンドは趣味で触り始めていた Vue を業務でも使うようになり、コンポーネントベースで書くフロントエンドのコーディングの楽しさを覚えつつも、 1000行以上のVue ファイルを目の当たりにするなど、複雑化や肥大化することのつらみを知りました。 他には、1年通してマイナンバーに関連する機能設計を行ない、法律や制度が絡む機能の設計の難しさに悪戦苦闘したりもしてました。 とはいえ、2020年は2019年までと比べて業務の中で新しい技術への出会いが多い年になり充実した仕事を多くできた気がします。 振り返ってみると、チームの異動をしたことが、自分にとってかなりプラスになったなぁと思います。

プライベート

OSS

ちょうど今年の初めに、今年はOSS活動をしてみたいと考えて、目標の1つとしていました。 Vue を学び始めた頃でもあったから、Vue関連のライブラリとかで貢献できたらいいな、なんてことを思ってた気がします。 ちょうど仕事では Vue のコンポーネントライブラリである Vuetify を使っていたので、Vuetify のissue に目を通してみたら自分でも直せそうな BugFix の Issue があったので、トライしてみました。それが自分にとって初めての OSS活動となりました。 とても小さな修正でしたが普段使ってるライブラリに自分のコードがマージされる喜びを知り、OSS活動に対する敷居が少し下がったので、挑戦してみて良かったと思ってます。 そこから、Vuetify や、同じくVue のコンポーネントライブラリである Buefy で自分でもできそうな Bugfix や Feature のIssue をいくつか見つけて対応したりしました。 また、ちょうど JavaScript を改めて体系的に勉強しようと JavaScript Primer のWeb版を読んでいたときに、画面右下にあるIssue報告用のボタンのデザインを少し変えたらちょっとだけ見やすくなるかななんてと思って、Issue を挙げてみたら受け入れてもらえたので、そのまま提案した内容を実装をして、ここでも簡単な機能追加?を経験することができました。

JavaScript Primer - 迷わないための入門書 #jsprimer

コード以外の部分だと、今年は Vue3 がリリースされて、それに合わせて翻訳プロジェクトが立ち上がっていたので、それにも参加することができました。翻訳プロジェクトでは、結構な数のページに対して、ページごとに翻訳の Issue 作られていました。でしたが、多くの人が手をあげていて、あっというまに全ての担当者が埋まっていくのをみて、Vue のコミュニティがとても賑わっていることを改めて強く感じました。 また、この翻訳の際に、アクセシビリティ関連のページを担当したことで、これまでよく理解していなかったアクセシビリティに大して興味を持つことができました。

その他

コロナの影響でほとんどの勉強会がオンライン開催になったこともあり、多くの勉強会に参加することができました。 フロントエンド関連のものに多く参加しましたが、フロントエンドの開発に興味を持ち始めていた一方で、 他の会社フロントエンドのレベルの高さや、フロントエンドエンジニア として働いている人たちの知識の多さを実感しました。 そんなこともあり、フロントエンドの領域でもっと開発していきたいと感じるようになって転職活動をしたりもしました。 カジュアル面談を何社かしていただいて、その中で1社だけ面接を受け、ありがたいことに内定をいただくことができたので、来年の2月からはフロントエンドにより特化して働くことができそうです。

おわりに

あんまり色々できなかったなと思っていたのですが、 去年の自分が今の自分を見たら、それなりに満足しそうだなとも思えるので、 意外と奮闘できた2020年だったのかもしれません。 来年も、今の自分が満足できる年になるように頑張りたいところです。

【TypeScript】基本型のまとめ

この記事の内容

TypeScriptは体系的に学んだことなかったので、
改めて公式ドキュメントを読んでいくことにしました。

その1回目として、Basic Typesの章を読んだので、そのまとめをまとめておこうと思います。

TypeScript: Handbook - Basic Types

Boolean / Number / String

JavaScriptと同じ。
真偽値、数値、文字列(順不同)。

Array

配列を表す型。
書き方は2通りある。

let list1: number[] = [1, 2, 3]; // 1. 型名[]
let list2: Array<number> = [1, 2, 3]; // Array<型名>

Tuple

Arrayのそれぞれの要素に対して、型指定して宣言ができる型。

let x: [string, number];
x = ["hello", 10];// OK
x = [10, "hello"];// Error

要素には、配列と同じようにアクセスできる。

console.log(x[0].substring(0)); // "hello"

Enum

数値をひとまとまりにして、名前付けして型宣言ができる。いわゆるEnum
値を指定しなければ0からインクリメントされた値となる。
指定すれば、そこからインクリメントされた値となる。
※以下の例参照

enum Color {
    Red = 1,
    Green,
    Blue = 18,
    Pink,
}
console.log(Color.Red)// 1
console.log(Color.Green)// 2
console.log(Color.Blue)// 18
console.log(Color.Pink)// 19

index指定してアクセスすることで、名前を取得できる。

console.log(Color[1])// Red
console.log(Color[2])// Green
console.log(Color[18])// Blue
console.log(Color[19])// Pink

Unknown (v3.0 ~)

未定の型としてunknownで定義できる。
ユーザーの入力値によって、動的に型が変わりうる場合などに使用する。

let notSure: unknown = 4;
notSure = "maybe a string instead";

// OK
notSure = false;

また型ガードetcによって型が定まるまで利用できない。

declare const maybe: unknown;
const aNumber: number = maybe; // Error: Type 'unknown' is not assignable to type 'number'

if (maybe === true) {
    const aBoolean: boolean = maybe;// OK, 型ガードによってmaybeはbooleanになっている
    
    const aString: string = maybe;// Error, booleanなので、string型の変数には代入できない
}

if (typeof maybe === "string") {
    const aString: string = maybe;//OK, 型ガードによってmaybeはstringになっている

    const aBoolean: boolean = maybe;// Error, stringなので、boolean型の変数には代入できない
}

Any

3rdパーティライブラリ使うときなどに、型チェックで苦戦することがある。
そういう時の回避策としてany型を使用できる。
any型を指定すると、コンパイル時の型チェックの対象から外れるためコンパイルエラーを回避できる。
しかし、コンパイル時の型チェックこそTypeScriptの恩恵が得られる部分なので、any型は極力使わないようにするべき。

let looselyTyped: any = 4;
looselyTyped.ifItExsists();// OK
looselyTYped.toFixed();// OK

また、any型はネストされた下位のプロパティにも伝播する。

let looselyTyped: any = {};
let d = looselyTyped.a.b.c.d; // aもbもcもdもany型になる

Void

any型がすべての型を含むのとは反対に、型を持たないことを表すのがvoid型。
戻り値を持たない関数の、戻り値の型として使用するのが一般的で、変数の型として使用することはあまりない。
※その場合、null("strictNullChecks"が無効の場合のみ)かundefinedしか割り当てられないため。

function warnUser(): void {
    console.log("This is my warging message");
}

let unusable: void = undefined;
unusable = null; // OK, ただし '--strictNullChecks' ではない場合

Null / Undefined

undefined値とnull値に対応する型としてそれぞれundefined型、null型が使用できる。
void型と同じく、単体で使用する用途はない。
後述するように union typeによる使用が一般的。

// これらの値しか割り当てできない
let u: undefined = undefined;
let n: null = null;

undefined値とnull値は他のすべてのタイプのサブタイプとなる。
つまり、numberの変数に対し、undefined値やnull値を割り当てられる。

ただ、"—strictNullChecks"指定をしている場合は、null値はunknown型、undefined値はunknown型とvoid型にしか割り当てができなくなる。
例えば、stringかnullかundefinedが入る変数を定義したいときは、以下のようにunion typeを使って、型定義できる。

let nullableString: string | null | undefined = null;

Never

neverは何もないことを表す型。例えば、必ずエラーを投げる関数の戻り値として使用する。
変数は型ガードによって絶対に真とならないように狭められた場合にneverになる。
neverはすべての型のサブタイプとなり、すべての型に割り当てることができる
一方で、どの型もneverのサブタイプとならないので、neverに割り当てることはできない。
(never自身は除く)
any もneverに割り当てることはできない。

let a: string = "hoge";
let func1 = (): never => {
    throw new Error();
};
a = func1();// neverをstringに代入 ※実行時はerror
let an: any = {};
let n1: never = an;// これは不可
let n2: never = func1();// never自身はOK

Object

object型はプリミティブでない型を表す。つまり、number, string, boolean, symbol, null, undefined以外の型である。
object型を使うと、Object.create()のようなAPIをより適切に表せる。

declare function create(o: object | null): void;

//以下はOK
create({ prop: 0});
create(null);

//以下はNG
create(51);
create("string");
create(false);
create(undefined);

Type Assertions (型ガード)

開発者の方がTypescriptより値の型を知ってるケースがあり、そういう場合にType assertionsを使うことで、型をコンパイラに伝えれる。
ほかの言語でいうところのキャスト。
方法は2通りある。

  • asによる型ガード
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
  • <>による型ガード
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;

どちらを使うかは好みによるが、TSXではasによるものしか使用できない。

まとめ / 感想

改めて学習すると、知らなかった仕様を色々知ることができました。
(strictNullChecksの有無による違いなど)
引き続き、次の章も進めていきたいと思います。

【React Hooks】【TypeScript】公式チュートリアルからのReact入門

はじめに

僕は今までフロントエンドでは、Vue.jsを主に使ってましたが、 複数のフレームワークを知っていた方が結局は、 個々フレームワークについてもより深い理解ができると思い、 Reactの学習を始めてみました。

Vue3でComposition APIが導入されTypescriptが使いやすくなったので、 既に広くTypescriptと組み合わせて使われているReactも知っておきたかったというのも動機の1つです。

ゴール

ひとまず次のようなゴールを設定しました。

  • 基本的なReactの考え方、書き方が分かる
  • React Hooksの考え方、書き方が分かる
  • Reduxの考え方、書き方が分かる
  • Typescriptを使ったReactの書き方が分かる

進め方

公式ページにチュートリアルがあったので、まずはそのチュートリアルでReactの基本を学習し、 そのままそのチュートリアルで使ったプロジェクトを使って Hooksなども学んでいきました。

チュートリアル:React の導入 – React

具体的には次のような感じで進めました。
1. チュートリアルに従ってReactでオセロゲームプロジェクトの作成
2. コンポーネントごとにファイルを分割
3. Styled Componentを導入
4. クラスベースのコンポーネントを関数コンポーネントに変更し、Hooksを導入
5. Typescriptを導入


チュートリアルのプロジェクトだと、Reduxの使いどころが見えなかったので、
このプロセスでReduxの学習するのはいったん諦めました。

1. チュートリアルに従ってReactでオセロゲームプロジェクトの作成

このステップは、チュートリアルを読みながら手を動かしていました。
開発環境を立てる他に、ブラウザ上で実行していく手順も書かれてましたが、
プロジェクトの構成やVscodeでの書き心地も知りたかったので、 開発環境を立てる方法で進めていきました。
チュートリアル:React の導入 – React

このチュートリアルを通して次のようなことを知ることができました。

  • クラスを使ったコンポーネントの作成方法
  • ReactDOMによるレンダー方法
    → Vue2.xと同じで、指定したコンテナの子要素としてレンダーするみたいです
  • React Devtoolsを使ったコンポーネントごとの状態の見方
  • Propsの使い方やJSX記法

2. コンポーネントごとにファイルを分割

チュートリアルだと、index.js1つのファイルにすべてのコンポーネントを書く形だったので、 コンポーネントごとにファイルを分割していきました。
3つのコンポーネントのみだったので、大きな作業ではありませんでした。

3. Styled Componentを導入

1つのCSSファイルによるスタイリングになっていたのを、
コンポーネントごとにスタイルを当てるために、 Styled Componentというライブラリを入れました。

次のような部分で少し躓きました。

4. クラスベースのコンポーネントを関数コンポーネントに変更し、Hooksを導入

チュートリアルでは、クラスによるコンポーネント作成が主だったのですが、
関数型コンポーネント(状態を持たないコンポーネント)に変更していきました。
そしてそれに伴い、React Hooksを導入しました。
コンポーネントに状態を持たせないようにして、thisを使わないようにする考え方はここらへん始まってるんですかね。

5. Typescriptを導入

初めにTypescriptを入れてしまうと、純粋なReactへの理解の妨げになる恐れがあったので、 最後のステップに持ってきました。
既に多くのTypescript × Reactのプロジェクトが普及してることもあり、 大きな躓きなく型付けを行うことができました。

全体を通しての感想

1日使ってチュートリアル+αでReactを使ってみて、
雰囲気はつかむことができました。
ただ、Reduxは試せなかったり、React特有の辛みみたいのも今回は分からなかったので
次はもう少し大きめのプロジェクトを作ってみて、そこらへんの理解もできたらなと思います。

ちなみに、今回使ったチュートリアルのレポジトリはこちらです。
GitHub - ryo-gk/react-tutorial-ts命名など雑な箇所がある点はご容赦ください。

【Vue.js】Vue3のTeleport(Portal)の使い方

この記事の内容

Vue3.0で追加される機能の1つであるTeleportを使ってみたので、
どういう時に使うのか、どのように使うのか、感想を書いてみようと思います。

※Vue3の環境構築については、下記に書きました。
【Vue.js】Vue-cliでVue3の開発環境を構築する - ryoのぼやき

Teleportでできること

Teleportを使うことで、
コンポーネント内の一部を、
DOM上の任意の位置に移動させることができます。

どういう時に使うか

基本的に、Vue.jsではコンポーネントをベースとしてUIを構築します。
そうすることで、スタイルやロジックなどをコンポーネントに閉じることができるメリットがあります。
しかし、コンポーネント入れ子構造が深くなった時に、
コンポーネント自身の外側に、UIを持っていきたいシーンが出てきます。
そういった時がTeleportの使い時です。
例えば、モーダルが主な利用シーンとして挙げられます。

どのように使うか

例えば、何かしらの結果を表示するResultというコンポーネントがあるとします。
(※templateのみ抜粋)

<!-- Result.vue -->
<template>
  <Teleport to="#result-location">
    <div class="result-panel" v-show="isShowResult">
      <div>Result is...</div>
      <span>{{ result }}</span>
    </div>
  </Teleport>
  <button @click="showResult">Show Result</button>
</template>


そして、Home.vueで、Resultコンポーネントを持つとします。
(※templateのみ抜粋)

<!-- Home.vue -->
<template>
  <div id="result-location"/>
  <Result/>
</template>


使い方は、
1. タグで、他のDOM上の位置に移動させる部分を囲う。
2. タグに to="セレクタ"で移動させる位置のセレクタを指定する。
だけです。

上の例だと、ボタンを選択すると、
Home.vueの<div id="result-location"/>
<Teleport>で囲った部分が表示されます。

※Sample
f:id:greko_prg:20200506225751p:plain


補足

PortalからTeleportに

このTeleportですが、
もともとは、Portalという名前で実装されていました。
しかし、WICGのPortalsとコンフリクトしていたという理由から、
Teleportという名前に変更されたようです。

Portals


targetからtoに

また、セレクタを指定するプロパティのtoですが、
これも前は、targetという名前で実装されていました。
こちらも、WICGのPortalとのコンフリクトを避けるという理由で、
toに変更されたようです。

まとめ

Vueでは、入れ子構造が深くなることで、
きれいな形で実装ができず困るシーンはよくあると思います。
それが、このTeleportが解決の糸口になってくると思うので、
うまく使っていきたいと思いました。

参考

[Teleport RFC]

rfcs/0025-teleport.md at master · vuejs/rfcs · GitHub

[Rename to ]

refactor: rename `<portal>` to `<teleport>` · vuejs/vue-next@eee5095 · GitHub

[kazuponさんのスライド]

まもなくやってくる Vue.js 3 - Speaker Deck

【Vue.js】Vue-cliでVue3の開発環境を構築する

この記事の内容

Vue3.0では新しい機能がいくつか追加されるので、
自分で触って試してみたいと思ってる人も多いと思います。
今回はvue-cli-plugin-vue-nextを使って、 Vue3.0の開発環境を構築する方法を紹介しようと思います。

------※7/29 追記------
vue-cliのv4.5.0を使うことで、vue createコマンドでvue3のプロジェクトが作成できるようになったようです。(オプション選択時に3.xを指定できます)
v4.5.0は、

npn install -g @vue/cli@next

でvue-cliのバージョンを上げることで使えるようになります。

------------------

vue-cliのインストール

ここは、Vue2.0以前と同じです。 既にVueを使っていれば、
入っている場合が多いと思いますが、
一応書いておきます。

ターミナルを開いて、以下のコマンドです。

$ npm install -g @vue/cli

プロジェクトの作成

vue-cliをインストールしたら、 プロジェクトの作成をします。
これもVue2.0以前と同じです。

$ vue create vue-next-trial

vue-next-trialはプロジェクト名なので任意です。 ※いくつかのオプションについて質問されますが、自由に選択してください。


ここまでの手順の詳細が知りたい場合は↓こちらを参考にしてください。
Vue CLI

Vue3.0にアップデートする

プロジェクトが作成出来たら以下のvue-cliのコマンドを使って
プロジェクトをVue3.0(vue-next)へ対応させます。

#プロジェクト以下に移動
$ cd vue-next-trial

# vue3.0にアップデート
$ vue add vue-next

やらなければいけないのは、これだけです。
詳細は以下を参照してください。
GitHub - vuejs/vue-cli-plugin-vue-next: A Vue CLI plugin for trying out vue-next (experimental)

main.tsを確認してみる

さっそくmain.tsを確認してみます。

//main.ts
import { createApp } from 'vue';
import App from './App.vue'
import router from './router'
import store from './store'

createApp(App).use(router).use(store).mount('#app')

Vue3.0では、GlobalAPIが切り出されました。
これによって、
Vueの振る舞いを変えるようなオプション(use, component, mixin, directive, etc..)は
createApp()メソッドによって生成されるappインスタンスを介して使うようになっています。
(きちんとmain.tsもそのように変わっています。)
[参考]
rfcs/0009-global-api-change.md at master · vuejs/rfcs · GitHub

まとめ

こちら

This is for preview purposes only. There might be bugs and undocumented behavior differences from v2, which are expected.

とあるように、バグやまだ未対応の部分も少し見られます。
とはいえ、便利な機能が多く使えるようになるので、ぜひ試してみてください。

[その他Vue3について]
【Vue.js】Vue3のTeleport(Portal)の使い方 - ryoのぼやき

【Vue.js】なぜかimgが表示されない時の解決法とその理由

この記事の内容

Vueのプロジェクトで、画像を表示しようとした時に、
なぜか画像ファイルが読み込めず、表示がされないことがあると思います。
そのような問題が起こる理由と解決策を書こうと思います。


vue-cliにおけるsrcの読み込みについて

画像が表示されない問題が起こるのは、
主にvue-cliで作成したプロジェクトが多いと思います。
なのでまず、vue-cliにおけるsrcの読み込みについて簡単に説明します。

vue-cliで作成されたプロジェクトでは、画像ファイルを読み込む時に、
file-loaderurl-loaderを使います。(webpackがそのように設定されます)

file-loaderはファイルをpublicな場所に保存するのに使われ、
url-loaderは画像ファイルをbase64エンコードして出力するのに使われるものです。
(他の役割については、ここでは割愛)

つまり、内部的には

<img src="@/assets/sample.png">


createElement('img', { attrs: { src: require('@/assets/samplge.png')}})


<img src="data:image/png;base64, 44GK5YmN44KC54mp5aW944GN44Gg44Gqdw==">



このようにコンパイルされるわけです。

[参考]

HTML and Static Assets | Vue CLI


https://blanche-toile.com/tools/image-to-base64


v-bindによって画像のパスを読み込もうとする場合

Vueを使う以上、v-bindで画像ファイルのパスを読み込みたいケースは多いです。
そして、画像が表示されない問題が起こるのは、このケースの時です。


<template>
  <img v-bind:src="imgPath">
</template>

<script>
  export default {
    data(){
      return {
        imgPath: '@/assets/sample.png'
      }
    }
  }
</script>



このようにv-bindでURLを読み込む場合、
パスはそのまま文字列として出力されます。

<img src="@/assets/sample.png>"


しかし、コンパイル後には/assetsフォルダはないので、
/assetsにある画像ファイルを読み込もうとしても見つけられず、
表示もされないというわけです。


解決法

require()を使う

require()を使い画像をモジュールとして読み込むようにしてあげます。

<script>
  export default {
    data(){
      return {
        imgPath: require('@/assets/sample.png')
      }
    }
  }
</script>


publicフォルダに置く

publicフォルダはwebpackに読み込まれることなく、そのままコピーされます。
つまり、コンパイル後もそのままpublicフォルダが残るので、
パスをそのまま指定しても問題なく画像が読み込めます。


まとめ

画像の読み込みに関しては、vueについてというよりは、
webpackやloaderの仕組みが関係していました。

このあたりは、まだ理解が甘い部分が多いので
積極的に調べて行けたらいいなと思いました。