2021年の目標

f:id:tjmschk:20210331194607j:plain

はじめに

こんにちはたじまです。もうすでに年が明けてから3ヶ月が過ぎ去ろうとする今日この頃、皆さんいかがお過ごしでしょうか。私はやっと重い腰を上げ、卒論で忙しいのを理由に決めていなかった目標を考えることにしました。

最近気がついたら一週間経っているを何度も繰り返しもう少し計画立てて人生を謳歌したいなと思い、初めてですが目標をまとめてみることにしました。

目標の決め方

目標を考える際、いろんな方のブログを参考にさせていただきました。特にこの二つの記事の目標設定フレームワークを参考にさせていただきました。

blog.p1ass.com

mesimasi.com

SMARTとOKRで比べた時、具体的で達成可能な目標を掲げるよりも若干気後れするくらい高いレベルを設定し7割の達成を目指すというOKRのほうが、夢みがちな自分に向いていると思ったのでこちらを採用します。

rework.withgoogle.com

また、ストレッチゴールとなる目標の立て方に悩んだので、とりあえず達成したい目標や願望や欲求をたくさん書き出してからカテゴリー分けをし、願望を取り除きました。そしてカテゴリーごとに残ったものからそもそも何故その欲求が生じたのか目的を考え、それらを包括する目標を設定するボトムアップ式で考えていきました。

OKR

初めに宣言すると、このOKRの開始は4月になってしまいましたが 締め日は年末に設定したい と思います。学生の間では年度が変わるごとに学年が変わることで心機一転することができましたが、社会人ではそのような人生のイベントは起こらないだろうと予想してのことです。

O: Web フロントエンドの知識と経験を得る

KR: 技術本を5冊読む

KR: OSS に3回コミットする

周りの人に比べ自分の技術力のなさ感じているので文字に起こして気を引き締めました。 「Webフロントエンドが好き」という言葉を感情だけではなく具体的な知識や経験を伴わせることが目標 です。学生時代に比べ社会人では自分の時間を確保しづらいと思うので成果指標は低めに設定してます(それでも2020年よりは多いですが)。

O: 自分の技術力を可視化する

KR: ポートフォリオサイト作る

KR: 技術ブログを9本書く

2つ目の目標も技術のことですがこれはつまりアウトプットです。自分って結局何ができるんだっけと説いた時にポートフォリオさえないのにWeb フロントエンジニア名乗っていいのかと自問自答しながらずっとやるやる詐欺をしていました。頑張ります。

O: 心身を健やかに保つ

KR: リングフィット or ランニングを100回する

KR: 複数のコミュニティに所属する

KR: 旅行に行く

心と身体を健康に保つのは楽しく生きる上で必須ですよね。最近リングフィット用のヨガマットとランニング用の高いシューズを買って体を動かすことにハマっています。この100回という数字は残りの9ヶ月の約4割を目標に設定しました。成果指標は七割達成を目指すのでだいぶ弱気ですがおそらく8時間労働に慣れないうちは就労後に運動できないと見積もっています。また複数のコミュニティというのは心の健康です。一つのコミュニティに依存してしまうと逃げ場を失いメンヘラになりやすいと思ったので入れました。

その他願望

OKRに含めるには願望がすぎるかなと思いつつでも書きたかったので番外編です。

  • 物事に関心を持ち自分の意見を持つ
  • TOEIC 700点取る
  • 漢字力つける
  • すぷらガチマ全部A帯

一つ目はこのこのツイートを見て以来思っていたことです。

自分の意見を大事にするよりも専門家の意見を聞いた上で立場を決めたいと思い過ごしていたらいつのまにか何にも興味がない人間になってしまいました。積極的に意見していこうということではなく、他人のコピーでは無い自分を見つけたいなと思っています。

英語力はずっと思っているんですがいつも願望で終わります。

おわりに

具体的な目標を立てるのは初めてなので多いのか少ないのか分かりませんが達成できるようにしていきたいです。まずやることはちゃんと記憶して忘れないことですね。

卒論終わったらやりたいことはもっとたくさんあったのに気付いたら春休みが終わってました。麻雀楽しい。とりあえず明日から始まる社会人生活が不安でどきどきしています。

プロフィール画像を刷新しました!

こんばんは、ついに東京都民になったたじまです。 いつもアドカレの時期にしかブログを書か無いので文頭に何を述べればいいか少し悩んでしまいました。

このブログではつい先ほどツイートした、新しいプロフィール画像について作るきっかけと作る工程など語っていきたいと思います。

実は公開するのがめちゃめちゃ恥ずかしくて完成してるのに Twitterプロフィール画像変えるまでに1日かかりました。 まだちょっと恥ずかしくて変なツイートしちゃいそうなのと完成するまでの工程を晒したいな〜と思ったのでメモついでにブログに書きます。

きっかけ

ずっとプロフィール画像をアイコン化したいな〜とは思ってたんですが口に出したのはこのツイートが初めてのようです。

ちなみに私は複数のワークスペースプロフィール画像管理に Gravatar を使っているのですが過去の履歴はこんな感じでした。懐かしいです。

f:id:tjmschk:20210323011358p:plain
プロフィール画像

下書き

とりあえず猫が好きなので猫の落書きをたくさんしました。私は落書きに iPad の Procreate というアプリを使っています。

f:id:tjmschk:20210323012415p:plain
アイコン候補落書き

最初右下の寝てる猫とか可愛いなと思いました。しかし猫をプロフィール画像にしている方を普段から Twitter で無限に観測しておりオリジナル性がないなということでボツに、ソフトクリームと猫を組み合わせたものに決定しました。

f:id:tjmschk:20210323013238j:plain
下書き決定版

トレース

ここから Figma を使いトレースを行いました。 画像の SVG 化です。

f:id:tjmschk:20210323013839p:plain
Figma でトレースしている図

Procreate で手振れなどは抑えてますがそれでも手書きなので幾許かの線の震えがあります。 それを考慮し下書きを手本にしながら綺麗なベジェ曲線を描いていきました。

f:id:tjmschk:20210323014450p:plain
SVG 化成功

配色

なんとなく最近桃色が好きなのでストロベリーアイスっぽくしようと心に決めていました。 Googleアイス イラスト と調べて、美味しそうなストロベリーアイスの色をキャプチャしてきました。 食べたら美味しそうなアイス にしようと思い派手なピンクよりリアルでありそうなピンクに近づけました。

そして白と黒の上に置き、霞んで見え無いかどうか調べたり、

f:id:tjmschk:20210323015039p:plain
アイコンっぽくしてみる

グレースケール化できるサービスを使い色の彩度を調節しました。

f:id:tjmschk:20210323015204p:plain
グレースケール化

こちらのサービスを使いました。

www.peko-step.com

他にもカラーユニバーサルデザインチェックも行ってみて、実際微妙でしたが自分の目標である 美味しそうな アイスの色にならなそうだったので諦めました。

ついに完成👏

f:id:tjmschk:20210323015920p:plain
schktjm.png

配色を決定してから一晩寝かせてやはりよかったので完成しました。 しかしやはり自分のプロフィール画像にするということは今後自分の顔になるということなので少しどころじゃなく恥ずかしかったです。

おわりに

これで卒論終わったらやりたかったことの一つが終わりました。間に合ってよかったです。 あとは自分のPFを作る(進捗なし)、2021年の抱負を書く(30%くらい) を頑張って社会人になるまでに完成させようと思います。

ここまでご覧いただきありがとうございました。

Composition API + Typescript で Vuex をリアクティブに安全に使いたい

こんにちは、毎年アドカレの時期しかブログを更新しないたじまです。(今年は少し頑張ったかな?)

この記事は、 Aizu Advent Calender 2020 の14日目の記事です。 13日目は虚無さん、15日目は spookydokey さんです。

さて、 Composition API といえば今年の 9/18 に正式リリースされたVue.js v3.0 が記憶に新しいかと思います。

github.com

この記事では、 Vue.js 2系 で先取り Composition API と、Vuex を使っているプロジェクトでなんとか型安全に Vuex を使えないかと足掻き苦しんだ末に私なりに出した解決方法をまとめてみました。私がこのプロジェクトを受け継いだ当時はまだ Composition API 周りのライブラリが発展しておらず、ベストプラクティスから程遠いかもしれないので、こうしたほうがいいよという助言をいただけるととても嬉しいです。

Composition API とは

簡単に紹介します。

Introducing the Composition API: a set of additive, function-based APIs that allow flexible composition of component logic. 1

Vue 2系 では宣言的な Vue インスタンスと HTML like なテンプレートにより、デザイナや経験の浅い開発者も簡単に使いこなすことができ、小規模から中規模なプロジェクトを簡単に構築することができます。 しかしながら大規模なプロジェクトでは、複雑なコンポーネントの推論の難しさや複数のコンポーネント間でロジックを抽出し再利用する方法の難しさ、TypeScript との相性の悪さから敬遠されがちです。

Composition API を含め Vue 3系ではコンポーネントを作る際の柔軟性と型推論を念頭に置いた設計により、複雑なコードもよりスマートに書くことができるようになりました。 RFC 詳しく書いてあるので気になる方はそちらを読んでください。

composition-api.vuejs.org

Composition API で Vuex を使う上での困った点

Composition API の強みであるロジック部分のモジュール分けなどはこのブログが参考になりました。

medium.com

このブログでは Vuex 関わる部分だけ簡単に書いていきます。

Vuex + TypeScript を使うときは、 vuex-module-decorators などのライブラリを使うことが多いと思いますが、 Vue Class Module の書き方に依存していて Composition API での使い方がわからなかったり、そもそも自分に経験がなかったりなどの理由で導入を見送りました。

下記のコードは、ボタンをクリックしたら Vuex の action 経由で text を fetch するというコードの一部です。 onClickgetText を dispatch しています。Vuex でいつもお世話になっている mapState などのヘルパー2 は this に依存するためつかえません。 そのため、action を下記のように文字列で指定する必要がありました。しかしそうすると少しの誤字でエラーになったりコードジャンプができないなど開発する上で不便に感じる点が多々ありました。

    setup(props: Props, ctx: SetupContext){
        const text = computed(() => ctx.root.$store.state.text);

        const onClick = () => {
            ctx.root.$store.dispatch("getText");
        }

        return {
            text,
            onClick
        }
    }

Composition APIで書いた Vue のコード全体

<template>
<div>
    <p>{{ text }}</p>
    <button type="button">Push!</button>
</div>
</template>

<script lang="ts">
import {computed, defineComponent, SetupContext} from "@vue/composition-api";

type Props = {
}

export default defineComponent({
    setup(props: Props, ctx: SetupContext){
        const text = computed(() => ctx.root.$store.state.text);

        const onClick = () => {
            ctx.root.$store.dispatch("getText");
        }

        return {
            text,
            onClick
        }
    }
    
})
</script>

改善前の vuex のコード

import Vue from 'vue';
import Vuex, { ActionTree, MutationTree, StoreOptions } from 'vuex';
import { RootState } from './type';
import API from './../api';

Vue.use(Vuex);

const mutations: MutationTree<RootState> = {
    setText(state, payload: { text: string }) {
        state.text = payload.text;
    }
}

const actions: ActionTree<RootState, RootState> = {
    async getText({ commit }) {
        try {
            const { text } = API.getText();
            commit('setText', { text });
        } catch (e) {
            console.error(e);
        }
    },
}

const store: StoreOptions<RootState> = {
    state: {
        text: ''
    },
    mutations,
    actions
}

export default new Vuex.Store<RootState>(store);

足掻き苦しんだ末の解決方法(仮)

このコード群をなんとかして読みやすくしたい(せめて補完がほしい)と悩んだ末に、参考にしたのがこの記事と Vuex+TS を使っていたプロジェクトのコードでした。

1. Vuex の state をリアクティブに使いたい

qiita.com

computed で逐一参照すれば問題ない話ではあるのですが、ひっぱってきた Vuex の state を reactive でひとまとめにしたい気持ちや階層化された値の監視に対応したいなどなどあったのでカスタムフックスにして切り分けました。(カスタムフックスは参考にした記事と全く同じです。)

ロジック部分のみに切り分けたモジュール

import { reactive, SetupContext } from "@vue/composition-api";
import { useVuexRef } from "./useVuex";

export default (ctx: SetupContext) => {
  const state = reactive({
    text: useVuexRef<string>(ctx, "text"),
  })
  const getText = async () => {
    await ctx.root.$store.dispatch("getText");
  };
  return {
    state,
    getText,
  };

Vuex の state をリアクティブにつかうためのカスタムフックス

import { onUnmounted, ref, Ref, SetupContext } from "@vue/composition-api";

export function useVuexRef<T>(context: SetupContext, key: string): Ref<T> {
  // 最後に as Ref<T> をしておかないと data.value の更新の部分で型エラーが起きる
  const data = ref<T>(context.root.$store.state[key] as T) as Ref<T>;

  const unwatch = context.root.$store.watch<T>(
    (vuexState: any) => {
      // 階層化された値の監視には対応してない
      return vuexState[key] as T;
    },
    (newVal: T) => {
      // refのvalueを更新すればコンポーネントが反応する
      data.value = newVal;
    }
  );

  onUnmounted(() => {
    unwatch();
  });

  // Refを返す
  return data;
}

さて、こうしてカスタムフックスに分けて書くことができましたが dispatch の部分や state の呼び出し部分が文字列で指定していてまだ不安があります。まだこの時点ではいいかもしれないのですが state の階層が深くなったりしていくと闇が見えるのでなんとかしたいです。

2. dispatch や state の呼び出しに補完を効かせたい

ほんとは TypeScript で方安全にしたいのはやまやまなのですが、知識不足&経験不足により方法が皆目見当がつかなかったため見送りました。

これを一言で表すと Vuex の action や mutation を定数として使うためのヘルパー関数です。以前 Vuex + TS でやっていたプロジェクトのコードを参考にしました。 (作成者は @uzimaru 君です。公開しよっかな言ってましたがまだっぽいです。)

type.ts

export type Action<A extends string, S, R = S> = {
  [key in A]: Vuex.Action<S, R>;
};
export type Mutation<M extends string, S> = { [key in M]: Vuex.Mutation<S> };

export const typesEnumeration = <T extends string>(
  obj: { [key in T]: any },
  prefix?: string
) =>
  Object.keys(obj).reduce(
    (acc, x) => ({ ...acc, [x]: prefix ? `${prefix}/${x}` : x }),
    {} as { [key in T]: string }
  );

ActionMutation は、Vuex.ActionVuex.Mutation 型のラッパーです。 Action や Mutation の関数一覧を union 型で宣言し、 Action に渡してあげることで関数の宣言忘れを防いだり誤字を防ぐことができます。

その上で、宣言した Action らを typesEnumeration を使い、関数名: それを文字列化したもの のオブジェクトに変換します。

mutation.ts

type MutationTypes = 'setText' | 'clearText';

const mutations: Mutation<MutationTypes, RootState> = {
    setText(state, payload: { text: string }) {
        state.text = payload.text;
    },
    clearText(state) {
        state.text = '';
    }
};
export const MutationTypes = typesEnumeration(mutations);
export default mutations;

actions.ts

type ActionTypes = 'getText' | 'clearText';

const actions: Action<ActionTypes, RootState> = {
    async getText({ commit }) {
        try {
            const { text } = API.getText();
            commit(MutationTypes.setText, { text });
        } catch (e) {
            console.error(e);
        }
    },
    clearText({ commit }) {
        commit(MutationTypes.clearText);
    }
}
export const ActionTypes = typesEnumeration(actions);
export default actions;

こうして、action.ts のアクションの中で mutation を MutationTypes.setText のように指定してコミットできます。 Composition API によって切り出したモジュールの中でも、 ActionTypesStateTypes を使うことで補完を効かせて Action や State を指定することができます。

import { reactive, SetupContext } from "@vue/composition-api";
import { useVuexRef } from "./useVuex";
import { ActionTypes } from "./../store/action.ts";
import { StoreTypes } from "./../store/index.ts";

export default (ctx: SetupContext) => {
  const state = reactive({
    text: useVuexRef<string>(ctx, StoreTypes.text),
  })
  const getText = async () => {
    await ctx.root.$store.dispatch(ActionTypes.getText);
  };
  return {
    state,
    getText,
  };

こんな具合で、開発をする上で最低限の環境を整えることに成功しました。

終わりに

Compotision API + Vuex のプロジェクト開発は現在私1人で行っていて、引き継いだ当初はあまり知見もなく不安だったのですが沢山の先駆者のブログや RFC の助けを借りなんとか1人で歩いて行けるコードになりました。 もし、 Vuex をもっと型安全に使えるプラクティスや助言などあったら是非コメントいただけるとうれしいです。

参考

Vue.js

【Vue3に備える】実務で使うComposition APIについて考える | by slont | Finatext | Medium

先取りVue 3.x !! Composition API を試してみる - Qiita

Vuexのstateをcomposition-apiでReactiveに使う - Qiita

技育展で敢闘賞をいただきました

こんばんは、たじまです。

肌寒い季節となってきましたね。

なんとこの度、株式会社サポーターズが開催のイベント技育祭で敢闘賞をとることができました!

talent.supporterz.jp

技育展ではそれぞれ八つのテーマに分かれていて、私たちは eeNotes で「チーム開発」で出ました。 eeNotesについてはチームメンバーのこの記事がわかりやすいと思います。

note.com

上から最優秀賞、優秀賞、敢闘賞で一番下から呼ばれたので少し悔しかったです。

チーム開発の他の参加者の方々も全員完成度が高く誰が優勝とってもおかしくないという状況だったのでとても悔しかったですが、賞を取れたことは本当に嬉しいです。 最優秀賞のCyQlone、優秀賞のtraQも他の作品もとても完成度が高く悔しいですが納得のいく結果です。笑

コロナが始まってしまって eeNotes をリリースしてからまだ一度もチームメンバーで打ち上げをしていないので賞金を使って打ち上げしたいと思います。

健闘ありがとうございました!

f:id:tjmschk:20200927013613p:plain
ありがとうございました by いいのん

追記: Twitterで嬉しい意見をいろいろいただけて嬉しかったので載せちゃいます!

デザイン周りは私がAll figmaで頑張ったのでめっちゃ嬉しいです!

疎結合なコンポーネントを心がけた話

こんにちは、たじまです。

最近はコロナに加え猛暑の毎日ですが皆さんいかがお過ごしですか? 私は外出ただけで溶けてしまいそうだったので大人しくエアコンの効いた部屋に閉じこもることにしました。

さて、今日は先月公開した eeNotes というサービスについてやってたことを少しだけまとめてみようと思います。

eenotes.work

よければ少しだけ触ってみてください。 Twitterもやってます!

eeNotes とは

Treasure2019のチームで開発したプロダクトをそのままリリースまでしよう!と継続開発して先々月の6月24日にリリースされた ノート共有サービス です。

簡単に説明すると、全員がノートのまとめ先を同じにしちゃえばテスト前にまとめるの上手い人のノートが見えるし、取ってない講義がどんな感じかわかるし、ノートを取ってる人は自分のポートフォリオとしても使えちゃう最高のサービスです。

私はデザインとフロントエンドを担当しました。

サイト経緯

Treasureで完成した時はこんな感じでした。

// TODO 昔のトップ画像探す。

ある程度やってる人ならわかる、Material Design ごりごりのデザインです。 整っていて、UIも複雑でなくわかりやすいのですが逆に言うと単調でぱっとしないですね。

継続開発を続けるうちに、このデザインだとあまり胸を張って宣伝できないなということになり旧デザインを一掃することになりました。

新しい全体像はこんなかんじ。デザインの作成は私のゴリ押しでFigmaを使いました。いいですよね、Figma

何をしたか

技術選定

さて、ここからやっと本題です。 今回はデザインの改修に合わせ、設計まわりは Atomic Design で進めていくことにしました。

圧倒的にフロント周りのタスクが多い中、CSSアレルギーを発症してしまう人が多かったので小さいコンポーネントCSS+αを書く人、APIをつなげる人でそれぞれ分担しました。 Atomic DesignでいうとCSSの人が ~Template までを担当して、APIつなげる人が Template ~ Page を触るといった方針です。

私はCSSを書く担当になりました。コンポーネント単体を確認するためにstorybookを使いました。

storybook.js.org

storybookとは

Storybook is an open source tool for developing UI components in isolation for React, Vue, Angular, and more. It makes building stunning UIs organized and efficient.

Storybookを使うとコンポーネントをカタログ一覧にまとめることができます。 また、スタイルやロジックを一つのコンポーネントに閉じ込めることができるので疎結合コンポーネントを作ることができます。

デザインがきっちり決まってる上でstorybookを使うとパズルゲームをしてるようでとても気持ちいいです。

実際に

CSS担当がどうつくるか考えてみます。

f:id:tjmschk:20200816213820p:plain
ユーザー画面

figmaのスクショです。 今回はこのユーザーのタグの部分を作ってみます。

f:id:tjmschk:20200816215212p:plain
この部分

実はこれとほぼ同じものが実はノート詳細画面にもありました。(右上のユーザー情報が出てる部分)

f:id:tjmschk:20200816215313p:plain
ノート詳細画面

内容は全く変わらず、当たるスタイルが変わってるだけそうなので再利用できそうですね。

|
|___Atoms
|         |___Tag
|         |        |___UserTag
|         |                 |___UserTag.tsx
|         |                 |___index.stories.tsx
|         |                 |___index.ts
|         |___Icon
|                   |___DeterminIcon
|                           |___DeterminIcon.tsx
|                           |___index.stories.tsx
|                           |___index.ts
|___Molecules
         |___Tag
                  |___UserTagGroup
                          |___UserTagGroup.tsx
                          |___index.stories.tsx
                          |___index.ts
         

ファイル構造はこんな感じになりました! (Codepen作ったんだけど動かない...😢)

storybookのファイル内ではコンポーネントを単体で表示しています。 (本番と同じようにするために背景だけstorybookのファイル上で付け足しました。)

storybookの画面はこんなかんじになりました!

f:id:tjmschk:20200816221216p:plain
ユーザー画面のほう

f:id:tjmschk:20200816221219p:plain
ノート詳細のほう

ユーザー詳細画面の方のタグと、ノート詳細にあるタグの違いはpropで分けられるようにしています。

UserTagGroup という名前にしちゃったのですが、そこにどんな種類の文字列が入るかとかはこのコンポーネントが知っておく必要はないかなと思い可変長の配列を入れられるようにしました。

storybook を使うとコンポーネントのpropをコードを変更することなくGUIで操作できるのでデバッグもしやすくなります。バージョンが上がってまた使いやすくなったみたいなので詳細はこちらから。

storybook.js.org

storybook使ってみて

メリット

圧倒的にこれはメリットでした。prop で渡す値を外部から変えたり、 action で変わるコンポーネントの挙動などを単体でテストできたのでバグが少なくすみました。

デメリット

  • Files changed が増える
  • (慣れてないと)実装にかかる時間も増える
    f:id:tjmschk:20200816224807p:plain
    これはとあるフロントの1pr

と言う感じでした。これはファイル構造のせいもあるのですが export する用の index.ts, storybookのファイル、コンポーネントの中身のファイルと一つ作るだけで3つのファイルが誕生するので、 1 pageつくるのに差が大きかったです。 また安心安全にかけるのですが慣れていなかったり速度を優先する場合には向いてないのかもしれません。

終わりに

今回は storybook について言及させていただきました。自分的にとても体験が良かったのでチームメンバーにも是非進めていきたいところです。

ありがとうございましたー!

おまけ

同じチームの仲間が eenotes の記事を書いているので読んでみてください!

qiita.com

qiita.com

qiita.com

note.com

2019年爆速振り返り

今年も風のように早かった2019年を思い出だけにしたくないので爆速で何やったか振り返ってみます。

この写真選んでるときすでに年越してしまったのですが、忙しかった記憶をそのまま思い出にしたくなかったので目次録としてまとめてみました。

f:id:tjmschk:20200101040224j:plain
君がHOPEだ!

1月30日 (多分)新年LT?

  • (多分)zliの新年LTにでました。記憶にないです。
  • canvasでソートアルゴリズムの可視化したLTしました。

docs.google.com

3月9,10日 Web Frontend Challenge

  • CA開催のWFCに参加しました。
  • 初めてのインターンだったのでとても緊張してました。この時初めてCAさんにお世話になったのがきっかけでのちのCATechJOBに参加しようと決心しました。

f:id:tjmschk:20200101003705j:plain
wfc集合写真

tjmschk.hatenablog.com

3月19日 追い出しLT in aizu

  • 23期メンバーが卒業するので追い出しLTを企画&運営しました。
  • たしかこのLTが私が初めて企画&運営したLTです。

f:id:tjmschk:20200101004001j:plain
oidashi_lt

4月10日 welcomeLT

  • 気合いのある一年生をZliに入れようと開催したLT。
  • このとき来てくれた何人かの一年生は今や立派なzli部員です。

f:id:tjmschk:20200101004820j:plain

4月30日 平成最後のハッカソン by CA

f:id:tjmschk:20200101023843j:plain
平成ファイル

5月18日 inside frontend 参加

  • CAさんがスカラーシップ枠で募集をかけててフロントエンドをちょうどやってて興味があったので応募したらうかりました。
  • ご覧の通りモチベーションがすごい高い状態で行ったわけじゃないんですがフロントエンドのいろんな技術を勉強できてフロントに対するモチベがあがりました。

当時何がやりたいのかわからないけどとりあえず流れでフロントやってるみたいな感じだったんですが極めたくなったきっかけはこの辺だった気がします。

f:id:tjmschk:20190520212856j:plain
首からさげるやつ

5月29日 モブプロでTDD

  • その時期授業でTDDをやることがあったのですが、TwitterTDDでモブプロ会 という方のイベントをみて、楽しそうだなとおもい開催しました。

想像以上に上級生の方々がいっぱい来て嬉しかったです。

f:id:tjmschk:20200101024659j:plain

6月29日 初夏の大LT in aizu

  • 皆さんご存知の大LTです。

ほんとは春にやる予定だったのですが、運営の準備が遅れ初夏のLTになってしまいました。また、とてもギリギリまで準備をしていたので自分自身のLT内容がすごく薄くなってしまいました。

内容が薄いのは言い訳になってしまうのですが、やはりLTの内容を作る際はちゃんと事前準備期間を設けたいと思いました。

f:id:tjmschk:20200101025530j:plain
集合写真

8月12日 ~ 30日 Treasure

  • 楽しかったし勉強になったし同学年の同じようなことをやっている仲間と知り合えたのはほんとにいいインターンでした。

今でもtreasureの仲間たちの活動をtwitterでみて、自分も頑張ろうと背中を押されています。

詳細はこちら

tjmschk.hatenablog.com

9月15日 ~ 20日 北海道バイク旅

  • 人生の夏休み

ちょっと頑張りすぎてたので念願のバイク旅に1人で行ってきました。

大学生らしい夏休みを送りたいなとおもいバイクでひとり、カプセルホテルやゲストハウスなどに寝泊泊まりました。

雨が多くて寒かったのが少し残念です。またいきたい。

f:id:tjmschk:20200101031056j:plain

9月21日 Summer Intern LT 2019

  • カーーズ君方が企画する100人規模のLT会に登壇してきました
  • バイク旅が終わり北海道から帰ってきた足で東京にいきました。なかなかハード。

VOYAGE GROUPのインターン参加者代表として登壇してきました。参加者の生の声を聞く、という趣旨で開催されたLT会でしたが、ここまでの規模のLT会で登壇するのは初めてだったのでいい機会になりました。

【学生限定】サマーインターン参加者によるLT会 - connpass

f:id:tjmschk:20200101031627j:plain
登壇写真

6月 ~ 9月 ATOM ハッカソン

  • 会津バスが主催する Aizu Transportation Open-data Marathon という長期型ハッカソンに参加していました。
  • 唯一のチームメイトが音信不通になったり、結局北海道行く前に1週間ハッカソンをしてしあげたりと大変でしたが、準優勝しました。

f:id:tjmschk:20200101032007j:plain

10月2日 インターン報告会&進捗どうですかLT

  • 後輩主催で手伝いをしました。

f:id:tjmschk:20200101032321j:plain

10月4日 エンジニア女子会

  • サポーターズCoLabの主催する女子会に参加してきました。

ここで繋がったエンジニアの方とまた後日BBQに誘っていただいて、コミュニティの輪を広げることができました。

周りが男性ばかりなのに不満があるわけではないんですが、やはり同性と話す機会が少ないのは参ってしまうので参加してよかったです。

f:id:tjmschk:20200101032611j:plain f:id:tjmschk:20200101032618j:plain

10月26日,27日 JPHacks

zliの仲間たちとハッカソンに参加してきました。

プロダクトとしてはすごいちゃんと仕上がったんですがインパクトに欠けたせいか思い通りの結果には至りませんでした。

f:id:tjmschk:20200101033101j:plain
首から下げるやつ

11月2日 秋の大LT 2019 in aizu

  • 皆さんご存知の大LTです

この会は今までの大LTからはかなり改変し、改善していったのですごい大変でした。

結果的にうまく行ったのですがやはり早めに準備しなければとおもいました。

f:id:tjmschk:20200101033351j:plain

11月7日 ~ 29日 CA Tech JOB in CATS

  • 皆さんご存知 #catechjob に参加してきました。

一言では言い表せない学びがありました。

まだ振り返りブログ書いてないぞ???? この辺後日ブログのリンクに差し変わります。

f:id:tjmschk:20200101033716j:plain
catechjob

11月10日 パソコン甲子園 zli展示

  • PCKに展示させてもらいました。

f:id:tjmschk:20200101035702j:plain

12月14日, 15日 温泉ハッカソン

結果温泉施設でハッカソンではなかったんですが、一泊二日山奥にこもって開発&みんなで豚汁をつくるという最高の環境をつくることができました。

f:id:tjmschk:20200101034026j:plainf:id:tjmschk:20200101034111j:plain

12月22日 HOPE Day by NewsPicks

  • NewsPicks主催の未来の若者のためのイベント。

自分の視野を広げるために参加してきました。 会津は情報単科大学なので、大学で情報系じゃないことを学びんでいる学生が今何を考えているのかを知るために参加してきました。

f:id:tjmschk:20200101035940j:plain
HOPE Day by NewsPicks

12月24日 未来大 x 会津大 対バンLT会

  • よく外に行くと会津とはこみがよく比べられ、ライバル認識せざるを得なかったはこみさんとクリスマスイブにLT会をしました。

一言でいうと楽しかったです。 やりたかったLT会のライブ配信もできました。

f:id:tjmschk:20200101034324j:plain

おわりに

振り返って反省してみると、私はやりたいと思ったことをどんどん企画してしまい忙しすぎて倒そうということが度々起こっていました。

私は旅行に行くときに予定をつくらず行き当たりばったりに行動するタイプなんですが、周りに迷惑をかけることもあってしまったので、ちゃんと事前に計画をしようと思います。

また自分の実力をちゃんと見極めてイベント企画しすぎで自分の時間がなくなる、ということがないように気をつけようと思います。

ここまでありがとうございました。 それではよい2020年を!

vue-routerのナビゲーションガードを使う

はじめに

この記事は Treasure Advent Calender 2019 16日目の記事です。 大幅に遅刻(2回目)して大変申し訳ありません。

adventar.org

今回は、12/24 のクリスマスイブに行った、未来大 x 会津大 対バンLT会 で扱ったネタを書いていこうと思います。

speakerdeck.com

はじめていきます。

今回簡単なテストアプリのリポジトリはこちらです。

github.com

やりたいこと

認証が必要なAPIを使用している際、 session token が切れていた時に、/login に飛ばしたい。

アプリ構成としては以下な感じです。

f:id:tjmschk:20191228000535p:plain
architecture

各PageComponentのcreatedで、vuexのactionをdispatchし結果をstateにcommit、 Pageの生成時にstateの値を参照するという流れです。 今回はコンポーネントgreet: の後の文章を非同期で生成しています。

とりあえずtokenが有効かどうかを調べる isValidToken APIを生やしてもらいました。

solution1

方法

App.vue の created で、isValidToken を呼び、無効だったら /login に飛ばす。

結果

目的だった tokenが無効なら /login に飛ばす という処理はできたのですが、isValidToken 関数が非同期通信をしているため、tokenが無効というのが返ってきてから/login へ飛ばす処理の前にComponentのインスタンスが作られ、createdで呼んでいたAPIでのエラーが表示されていました。

Image from Gyazo

図としては以下の感じ。

f:id:tjmschk:20191228185437p:plain

solution2

方法

vue-routerの グローバルビフォーガード を使う。

グローバルビフォーガードとは

いつナビゲーションがトリガーされようとも、グローバル before ガードは作られた順番で呼び出されます。ガードは非同期に解決されるかもしれません。そしてそのナビゲーションは全てのフックが解決されるまで 未解決状態 として扱われます。

全てのフックが解決されるまで未解決状態として扱われます つまり非同期に解決されたとしてもインスタンスが作られず /login に飛ばせます。

ただし、この場合ナビゲーションがトリガー毎にリクエストを飛ばすのでパフォーマンス重視のアプリならやらない方がいいのかもしません。

追加したコード
const router = new VueRouter({
  routes
});

router.beforeEach((to, from, next) => {
  if (!store.state.isLoggedIn && to.path != '/login') {
    next('/login');
  }
  next();
});

※ 最初っからこっち使えよってわかるんですが↑の時は知りませんでした。無知の知

結果

Image from Gyazo

うまくいきました〜

おわりに

vue-routerのナビゲーションガードを使った場合、APIでの認証系エラーを表示せずログイン画面に遷移することができるようになりました。 しかし、ブログの途中でも言及しましたがこの方法だと画面遷移毎にリクエストを飛ばす必要があるためパフォーマンスを考えるとそんなよくなかったりするかも?

もしもっといい方法があったら教えてもらえると嬉しいです 🙇‍♀️

そしてTreasure2019のみなさん、アドカレ超遅刻してしまい申し訳ありませんでした。 迷惑かけた人には土下座するのでTreasureN次回誘ってください。