じまろぐ

めめ

13インチ MBPに合わせてポータブルなモニタを買った

f:id:nakajmg:20180822200345j:plain

MBPを15インチから13インチに変えた影響で作業領域が若干せまくなりました。出先でやる気を出したいときに作業領域を広げたいので小さめなモニタを探しました。

いろいろ見た結果、購入したのはこれ。

よさ

  • type-c対応
  • HDMI(mini)入力あり
  • 13.3インチ

大きさはMBP13インチとほぼ一緒。

type-c対応で給電含めてケーブル1本で完結するのがとても良いところ。

HDMI(mini)入力があるのもよくて、type-cだけだと現状mac以外に使い道がなくなるので、HDMIでいろんな機器に使い回せるのは高評価ポイント。

あまり使わないけどスピーカーも内蔵してる。

スタンド

付属品のスタンドが若干重いので、代わりにプラ製のこれを持ち運んでる。

ケース

画面保護用のケースが一切ついてないので、使わないときはエレコムの保護ケースに入れてる。ジャストサイズ。

ポケットがついてるのでtype-cケーブルとスタンドを入れてすっきり収納。

ケーブル

type-c to type-c なケーブルは付属してないので、Ankerの50cmのやつを使ってる。MBP13インチの左側にモニタおいてMBP右側のtype-cにつなげる長さ。

いいよ

この大きさ&重さであれば普通に持ち歩ける。ケーブルも1本で済む。

おすすめです。

vuex-connectでnamespacedなmoduleを使いやすくするヘルパーを作った

vuex-connectはVuexでReduxのconnectのようにstoreとコンポーネントを繋ぐやつ。

www.npmjs.com

コンポーネントとstoreを繋ぐ部分を切り離せて宣言的に書けて気に入ってる。mapStateとかVuexが用意してるやつ使わなくてもstoreの値を取り出せて注入できる。

namespacedなmoduleを繋ぐとき

たとえば次のようなstoreがあったとき

const store = new Vuex.Store({
  state: {
    foo: 'foo',
  },
  modules: {
    moduleName: {
      namespaced: true,
      state: {
        bar: 'bar',
      },
      mutations: {
        barMutation(state, payload) {
          state.bar = payload
        },
      },
      actions: {
        barAction({ commit }, payload) {
          commit('barMutation', payload)
        },
      },
      getters: {
        barbar: state => state.bar + state.bar,
      },
    },
  },
})

vuex-connectではこう、関数で書いて階層たどってreturn。

import { connect } from 'vuex-connect'
import MyComponent from './MyComponent'

export default connect({
  stateToProps: {
    foo: 'foo',
    bar: state => state.moduleName.bar,
  },
})(MyComponent)

mapXxxxxぽく書きたいからヘルパー作った

数が少なければいいんだけど多くなってくると毎回namespaceの階層まで記述するのめんどい、のでヘルパー関数作った。

www.npmjs.com

import { connect } from 'vuex-connect'
import { stateToProps } from 'vuex-connect-namespace-helper'
import MyComponent from './MyComponent'

export default connect({
  stateToProps: {
    foo: 'foo',
    ...stateToProps('moduleName', {
      bar: 'bar',
    }),
  },
})(MyComponent)

mapXxxxxとかと同じように1つ目の引数にnamespaceを指定、そのあとそのmoduleのlocal stateを指定する。

ヘルパーがやってるのは指定されたnamespaceとstate名をいい感じにマッピングして、moduleのstateを返す関数に変換してるだけ。

API

内部的にやってることはほぼ同じだけど一応わけてある。

helperFunction(namespace, options) -> Object

  • stateToProps
  • gettersToProps
  • mutationsToEvents
  • mutationsToProps
  • actionsToEvents
  • actionsToProps

vuex-connectおすすめ

VuexのmapXxxxxを無計画に使ってるとつらみになりがちで

  • storeと密結合になるからmapXxxxxをpresentationなコンポーネントには使いたくない
  • コンポーネントごとに小さなcontainerを都度作るのつらい
  • pageレベルのcontainerにやらせるとmapXxxxxが増えまくってつらい
  • コンポーネント$emitをバケツリレーしてcontainerでmapMutationsとかした処理呼ぶのつらい

とかとか。

この辺りをスッと綺麗に書けるようになるので、Vuex使う人は一度試してみるのおすすめです。

starください。

github.com

github.com

デスク付きエアロバイクがいい感じ

デスク付きのエアロバイク FlexiSpot V9 を購入した。

運動できる環境がすぐそこに

家にデスクバイクがきたことで、運動しないことに言い訳ができなくなった。そのおかげで毎日運動するようになって、心身ともに整ってきたような実感がある。

運動しながら仕事してると、頭が冴えてきて集中力が増す気がする。リモートワークしてる人には特におすすめしたい。

値段見てたっかいなーと思ったけど、買ってよかったなと思えている。

家で仕事する人、最近ジム行けてないなって人、手軽に運動する環境が欲しいって人にはおすすめできる。

邪魔になったら売ればいいし、足を畳んでデスクを外せばめっちゃ小さい。

きっかけ

デスク付きバイクの存在を知ったきっかけは👇のレビュー記事。

gigazine.net

購入の決め手は本体のスリムさと移動が楽なキャスター式なところ。

使用感

f:id:nakajmg:20180429143222j:plain

購入してからの3週間、ほぼ毎日のように仕事or遊びながら1時間以上は漕いでる。多い日は4時間くらい。

エアロバイクとしての安定感はばっちり。デスクの大きさも丁度よい。始めのほんの数分は漕いでることに意識を少しもっていかれるが、しばらく経つと漕いでるのを忘れる。

漕いで十数分してくると汗ばんできて、少し回転を早めに漕ぐとシャツが汗びっしょりになる。汗をかいたあとの風呂最高。

大きさ

デスク付きのバイク、調べてみるとそこそこの種類が世にはあった。中にはけっこう安いやつもある。ただそのほとんどが設置スペースとして狭くないスペースを必要とするのと、本体の移動が大変そうである。

FlexiSpot v9の地面に設置してるキャスター部分の辺を測ってみると横が55cm、縦が80cm程度。

決して小さくはないが部屋に置いてあってもそこまでの圧迫感はない。

キャスターによって簡単に移動できるので、気分によって向きを変えたり場所を変えたりしてる。

f:id:nakajmg:20180429143214j:plain

f:id:nakajmg:20180429143206j:plain

本体の幅はiPhone 6Sの縦幅より細い

デスクも十分な広さ

デスクの大きさは横50cm縦58cm程。パームレストというか肘置きみたいなのが5cm~8cm程度あるので縦で使えるのは50cm程。

f:id:nakajmg:20180429150619j:plain

写真はMacBook Pro 15インチ。macの横にマウスパッド置いてマウスでの操作も問題なくできた(漕ぎながらLoLやってみた)。

パームレストがあるので手の疲れが出にくいのがいい感じ。

このデスクは高さと縦方向の位置が調整できるので最適なポジションで作業できる。

本体にドリンクホルダーがあるが、漕いでると足に干渉することがあったので別途クリップ式のホルダーを購入した。

スタンディングデスクとしても使える

デスクの高さと縦方向の位置が調整できるので、スタンディングデスクとしても使える。家の中でスタンディングやろうとすると、棚の上とか箱を積んだりとかでめんどくさいので、この使い方は意外と便利。

室内でもシューズがあったほうが漕ぎやすい

機器のペダルは自転車と同じようなペダル。室内用にゴムのカバーが付属してるが、それでも漕ぐ時の安定感を考えるとランニングシューズの用なものがあるとよいと感じた。

高負荷では連続使用可能時間が短め

大きさを考えると仕方ないが、負荷を高めの設定にした場合、機器への負担が大きいため30分程度で一旦本体を休ませる必要があるのがすこし難点。ただめちゃくちゃ筋肉付けたいとかでなければ、8段階の4くらいの負荷で長めにやればよいかなと納得してる。

デスクバイクが来てからの変化

通ってたジムを解約した。

仕事の忙しさとか引っ越して距離が遠くなったとか色々理由つけて行かなくなりがちになっていた。それでも運動はしたいというモチベだけはあって、もういっそのこと家できっちり運動すればいいかと思うようになった。

Twitchでゲームの配信を見ながら漕ぐようなときは、両手が空いてる。そういうときはダンベルかチューブを使って上半身を動かすようにしてる。

これの影響か漕いでないときもウェイトとチューブでなるべく全身を動かすように努めるようになった。毎日筋トレしてると寝付きと寝起きがとてもよい💪

筋肉を増やしたいのでプロテインも毎回飲んでる。

これ美味しくておすすめ。今まで色々試したプロテインの中でもっとも味がよくてプロテインぽさがなかった。

ながら運動最高

ゲームばっかりしててもこれなら運動不足にならないぞ

家に長時間いる人にはほんとおすすめ

Vueのバージョンアップの内容を追いかける方法

CodeGridにてVueの2.1から2.5で追加された機能からいくつかピックアップして解説した記事を書きました。

どういった方法で更新を追うかについては触れていないので、ここに書いておきたいと思います。

ライブラリの更新を追う

こういった記事を書く書かないに関わらず、日頃から自分がよく使うライブラリ/フレームワークに関しては更新を追って追加された機能などを把握するようにしています。

更新を追うのは大事だと思っていますが、常日頃から意識して更新を追いかけてる人ばかりではないと思います。

そんな人でも、更新の追い方さえ知っておけば、ふと気が向いたときに差分をチェックできてすぐに追いつけるかと思います。

追い方

更新の情報はライブラリ/フレームワークによっていくつかのパターンがあります。

よくあるパターンとしてはGitHubリポジトリの次の箇所にあるパターンです。

  • releasesのノート
  • CHANGELOG.md

更新情報として何が書かれているかはリポジトリによりますが、追加した機能についてや、バグの修正について簡潔に書かれています。

また、オフィシャルブログのようなものを運営していて、そこで新しいバージョンの目玉機能などについて解説していることもあります。

medium.com

reactjs.org

blog.angular.io

基本的にはこれらの情報を見ておけば大まかにどのような変更があったのかを把握できます。変更の詳細については、紐付いているissueや、ドキュメントに追加された項目で確認します。

わかりづらい機能の場合は該当する機能のテストコードを見るのもオススメです。

Vueの場合

本題。

Vueの場合はreleasesのページにバージョンごとに細かく何が追加/修正されたかが一覧になっています。

github.com

おもな追加機能はマイナーバージョンが上がるときに追加されることが多いので、v2.x.yのxの数字が上がった箇所のリリースノートを見るとよいです。

稀にパッチバージョンで何らかの機能向上がある場合もあります。それを見つけるには、リリースノートのページで Improvements というキーワードでページ内検索をかけると見つけやすいです。

f:id:nakajmg:20180420142641p:plain

ドキュメントから見つける

追加された機能については、公式ドキュメントに追加されています。

API — Vue.js

ページ内検索で 新規 というキーワードで探すと追加された機能を見つけられます。

f:id:nakajmg:20180420142539p:plain

英語ドキュメントの場合は New in で。

f:id:nakajmg:20180420143006p:plain

Vueはドキュメントの更新もしっかりしているので、ドキュメントを見ておけば大丈夫なことが多いです。

おわりに

気が向いたときにでも更新を追いかけてみてください。

リリースノートやCHANGELOGには追加された機能だけでなく、バグの修正についても書かれています。

使っていて何か挙動が変だな?と思ったときは、パッチバージョンが上がって修正されていないか、もしくはissueが作られていないかなども合わせて確認するとよいかと思います。

WebStormでJestが設定ファイルを見てくれなくなったから設定した

WebStormのJest連携便利

WebStormはエディタの中でJestによるテストを走らせられる。テスト全体ではなく、テストケースごと(it,test)やdescribe単位でも走らせられる。

(左のくるくる記号をクリックするとテストが走る) f:id:nakajmg:20180327124930p:plain

テストケース増やしたときにそこだけ実行したりできてとても便利。

importのtransform

Jestはデフォルトでimportを解釈できないので、package.jsonjest.config.jsとかの設定ファイルでtransformを指定することになる。

SyntaxError: Unexpected token import が出るようになった

WebStormを2018.1アップデートにしたら設定が変わったのかなんなのかわからんけどテストケース単体で走らせたときにimpotを使ってるとこでエラーが出るようになった。

どうも単体でテストケースを実行した時のワーキングディレクトリがプロジェクトのルートディレクトリではなく、テストファイルのあるディレクトリになるように変更が入った雰囲気。

コンフィグファイルが参照できないのでtransformが出来ずエラーが出る状態。

Jestの設定を変える

探したらJestの設定がわかりづらいとこにあった。

npm scriptsの一覧の

f:id:nakajmg:20180327124942p:plain

歯車クリックして Edit npm Configurations を選択

f:id:nakajmg:20180327124939p:plain

でてくる設定の左ペインからDefaults > Jest を選択

f:id:nakajmg:20180327124934p:plain

この設定がデフォルトの設定として使われるので、Working directoryにプロジェクトルートのパスを指定。

これでテストケース単体で実行したときもこの設定が使われて、設定ファイルも見てくれるようになる。

VueコンポーネントのnameからCSSのクラスを付与するディレクティブを作ってみた

VueのSFCでのCSSの命名について以前書いた。

nakajmg.hatenablog.com

このSFCSSをやってくうえでクラス名を記述するのをなんとか楽できないか考えた。

この記事はその試行錯誤の軌跡である。

はじめに結論

コンポーネントnameからクラス名を付与するディレクティブを作ってプラグインをnpmに公開したが、最終的には普通にせっせと書くのが一番ベターなのでは?というところに辿りついたというお話。

めんどくさポイント

命名規則によって命名の手間は減ったが、classをフルで記述する必要があって変わらずめんどうだった。

<template>
  <div class="MyComponent">
    <h1 class="MyComponent_Heading">
      heading
    </h1>
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
}
</script>

<style lang="scss" scoped>
.MyComponent {
  &_Heading {}
}
</style>

nametemplateで参照してなんとか楽をできないかと考えた。

コンポーネントnameの参照

コンポーネントnameにつけた名前は、$options._componentTagで参照できるので、:classを使って次のように書ける

<template>
  <div :class="[$options._componentTag]">
    <h1 :class="[`${$options._componentTag}_Heading`]">
      heading
    </h1>
  </div>
</template>

が、かなりめんどうだしむしろ手間が増えてるような…🙄

methodsに定義してmixinとか…?

じゃあクラス名を返すメソッドを定義してヘルパーっぽく。mixinにすれば共通化できるし…

<template>
  <div :class="[className()]">
    <h1 :class="[className('_Heading')]">
      heading
    </h1>
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  methods: {
    className(childNode = '') {
      return `${this.$options._componentTag}${childNode}`
    }
  }
}
</script>

うーん微妙。:class="[className()]"とか毎回書くのだるそう

ならばディレクティブだ

ディレクティブにしたらまだマシになりそう

<template>
  <div v-class-name>
    <h1 v-class-name="'_Heading'">
      heading
    </h1>
  </div>
</template>

<script>
function bindClassName(el, binding, vnode) {
  const componentName = vnode.context.$options._componentTag
  const className = `${componentName}${binding.value || ''}`
  if (el.className.indexOf(className) !== -1) return
  el.className = `${className}${el.className ? ' ' + el.className :''}`
}

export default {
  name: 'MyComponent',
  directives: {
    className: {
      bind: bindClassName,
      update: bindClassName,
      inserted: bindClassName,
    }
  }
}
</script>

ディレクティブに文字列として渡さないといけなくて"'_Heading'"としないとならないのが癪に障るけど、それっぽさは出てる。

これがレンダリングされるとこうなる。

<div class="MyComponent">
  <h1 class="MyComponent_Heading">
    heading
  </h1>
</div>

vue-class-nameプラグインとしてpublish

👆のやつをプラグインにしてnpmにpublishした。

www.npmjs.com

使い方

インストール

npm i vue-class-name
import vClassName from 'v-class-name'
import Vue from 'vue'
Vue.use(vClassName)
<template>
  <div v-class-name>
    <h1 v-class-name="'_Heading'">
      heading
    </h1>
  <div>
</template>
<script>

export default {
  name: 'MyComponent',
}
</script>

:classでの動的なクラスの切り替えと親コンポーネントからのclassのマージについては動作確認済み。

おわりに

なんとかならんかと試して、最終的にプラグインとして公開してみたものの、処理の内容的にどこかしらパフォーマンスに影響でそうで微妙だから自分で使わなそう🤔

宣言的に書くのがtemplateの良いところだと思うので、めんどくさくてもCSSのクラス名は静的に書くのがベターなのではと思った。

おしまい

透明なSlackクライアントを作ってみた

f:id:nakajmg:20180306194547p:plain

タイトルの通り、背景が透明なSlackクライアントを開発合宿で作った。

モチベ

  • 画面共有してるときにチャット見える状態にしたい(ウィンドウのサイズは小さくしたくない)
  • 作業集中するとき公式クライアント終了させたいけど、案件のチャンネルとか見ておかないといけないチャンネルだけ見れるようにしておきたい

ということで考えたのが透明なSlackクライアント

Slack Real Time Messaging API

SlackのAPIにはいくつか種類がある。以前ステータスを変更するアプリを作ったときに使ったのはいわゆる普通のWeb API nakajmg.hatenablog.com

api.slack.com

これとは別に、Slack上で起こっているイベントをリアルタイムに受け取れるAPIがReal Time Messaging API。超雑に説明すると、このAPIを使えばSlackクライアントが作れる。

api.slack.com

WebSocketでリアルタイムにSlackで起こってる全イベントを受け取れるので、イベントをさばいて必要な情報をストアしたり表示したりすることでクライアントを構築する。

Electronで透明アプリ

Electronを使うと、背景色の透明なアプリができる。

new BrowserWindow({
    frame: false,
    transparent: true,
})
body {
  background-color: rgba(0,0,0,0);
}

作った

GitHub - nakajmg/SlaCast: slack comment viewer

実装した機能は次のとおり

  • チャンネルの選択
  • 選択したチャンネルのチャット表示
  • スレッドの展開
  • カスタム絵文字対応絵文字ピッカー
  • リアクションの表示
  • メッセージの送信

チャットの表示はアプリを起動したタイミング以降のものだけが表示できる。

Web APIと組み合わせれば過去ログも辿れるようにできるが、今回の目的と異なるので見送り。

使ったやつ

package.json

開発合宿ではあまり詳しくないものを使うようにしてるので、Vueを使わずReact+MobXを使ってTypeScriptで書いた。

SlackのAPIとのやり取りは公式のライブラリで十分だった(型定義がなくてつらかったけど) github.com

絵文字ピッカーはemoji-martにSlackに登録してあるカスタム絵文字を登録して使えるようにした。 github.com

f:id:nakajmg:20180307143032p:plain

emoji-martはVueで使える版もあって絵文字ピッカーつけたいときは重宝している。

使い方

electron-webpackとelectron-builderの作法を把握しきれず、パッケージングして動く状態にするのがめんどくさくて諦めた。

なので使いたい人がいたらgit cloneしてnpm iしてnpm run startでお願いします…

そのほか

アプリにサインインするにはManage PermissionでSign in with Slackを有効にする必要があります。

f:id:nakajmg:20171124185352p:plain

SlackのApp Directoryに乗せる審査を通していないので、Teamの設定でNon distributedなappのインストールが許可されてない場合にはサインインでエラーになります 。(PermissionのOnly allow apps from the Slack App Directoryが有効な場合)

また、インストールにAdminの許可が必要な場合(Approved Appsが有効な場合)にもサインインでエラーがでますが、インストールが許可されると使えるようになります。

Slack APIの可能性

今回Real Time Messaging APIを使ってみて、めんどくさいながらもSlackクライアントが自分で作れることが確認できた。

公式クライアントは複数チームに所属してる場合の体験があまりよくないように感じるので

  • 複数チームでサインイン
  • 選択したチャンネルを横並びに表示

できるようなクライアント作れば便利そうだなと思った