じまろぐ

めめ

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クライアントが自分で作れることが確認できた。

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

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

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

Airbnbで金沢8泊リモートワークをした話

1月の中頃から8泊9日で金沢を満喫しつつ仕事してきた。

f:id:nakajmg:20180217132226j:plain

三度目の金沢

金沢に行くのは三度目。前回の訪問が1年半前くらいで、観光地はほとんど訪問済み。

それでも金沢に行きたい理由は日本酒とご飯。金沢の日本酒好きだし、どこでお寿司食べてもだいたい美味しい。

今回は妻が長めの休みを取れたのと、金沢行きたい欲が高まってたタイミングが重なったので、長めの滞在を決断した。

Airbnbで宿探し

連泊になるとホテルは高い。そしてホテルだとくつろげないと思い、初めてAirbnbを使ってみた。

金沢で検索すると結構な数でてくる。そして安い。

www.airbnb.jp

この中から次の条件で探した。

近江町市場に徒歩3分くらいで行ける立地の部屋が見つかり予約。2名8泊でかかった金額👇

¥ 5850 x 8泊¥ 46800
清掃料金¥ 3000
サービス料¥ 6451
合計¥ 56251

部屋の感想

綺麗なワンルームのマンション。家電もそろってて2日目からは自宅のようにくつろげた。

3日経つとで「金沢に引越してきたんだっけ?」てくらい普通に生活してた。

写真は備え付けのテレビのHDMI外部入力を探す自分。

f:id:nakajmg:20180217130313j:plain

Switchの簡易ドック持っていってレゴワールドで遊んでた。

Wi-Fiが弱かった

泊まった部屋のホストが企業だったらしく、同じマンションの数部屋を管理してた。Wi-Fiが部屋ごとではなく、数部屋まとめて飛ばしてる感じで電波強度が弱くて使い物にならず。

結局IIJテザリングで仕事した。IIJめっちゃ速いし安定してて最高。クーポンオフにして3Gで使ってても気にならなかった。

金沢でのすごし方

自分は平日の日中は部屋でもくもくと仕事、お昼は外で妻とランチ。

妻は好き放題に金沢市街を探索。

寿司うまい

f:id:nakajmg:20180217130319j:plain

近くの市場で昼にお寿司食べて部屋に戻って仕事するのがとてもよかった。

カレーうまい

f:id:nakajmg:20180217132230j:plain

好き。

日本酒うまい

f:id:nakajmg:20180217130334j:plain

日本酒も存分に堪能。金沢のお酒はほんとに好みに合うのが多い。

日本酒の店で横にいた地元の人から美味しいおでん屋とか聞いたり、そういうのもよかった。

8泊した感想

すご くよい。超リフレッシュ。

観光で来るのとはまったく違う体験ができた。

もし東京から出るときには長めに民泊して、街を知ってから引っ越すのよさそうだな〜と思った。

金沢はまた行く。

勉強会とかなんかしらイベントやってるタイミングがあれば合わせるのもありかも。

Vueコンポーネントのビルド時に不要な属性をtemplateから取り除く

追記(2019/02/12)

vue-cli v3向けにはプラグインがある

github.com

テスト用にdata-test属性を使ってる

VueコンポーネントのテストをJest + vue-test-utilsで書いてる。

dataとかpropsの値によって状態が変化する要素のテストをするとき、要素の特定のためにクラス名使うといろいろ大変だからテスト用にdata-test属性を使ってる。

blog.kentcdodds.com

data-test属性を消したい

テストするときには便利だけど、あくまでテスト用で、リリースするときには消しておきたい。

特定の属性を消すReact用のbabelプラグインがあったけど、Vue用のは見つけられなかった。代わりにフォーラムで見つけたのがこれ。

forum.vuejs.org

vue-loaderのオプションで属性消せるよとのこと。

次のコードはフォーラムのコードからNODE_ENV の値見てるとことlodash依存を排除したやつ。

{
  compilerModules:  [{
    preTransformNode(astEl) {
      const { attrsMap, attrsList } = astEl
      if (attrsMap['data-test']) {
        delete attrsMap['data-test']
        const index  = attrsList.findIndex(x => x.name == 'data-test' )
        attrsList.splice(index, 1)
      }
      return astEl
    }
  }]
}

これでdata-test属性が消えて万歳🎉

nuxt.jsで同じことしたい

nuxt.config.jsbuild.extendでvue-loaderのオプションを指定する。

module.exports = {
  build: {
    extend (config, ctx) {
      if (!ctx.isDev) {
        const vueLoader = config.module.rules.find(rule => rule.loader === 'vue-loader')
        vueLoader.options.compilerModules = [{
          preTransformNode(astEl) {
            const { attrsMap, attrsList } = astEl
            if (attrsMap['data-test']) {
              delete attrsMap['data-test']
              const index  = attrsList.findIndex(x => x.name == 'data-test' )
              attrsList.splice(index, 1)
            }
            return astEl
          }
        }]
      }
    },
  }
}