いがにんのぼやき

WEBエンジニアのブログ。IT、WEB、バンド、アニメ。

Vue.jsとか使って時間管理マトリックスのWEBアプリを作ってみた

Time Management Matrix

作ってみた。リポジトリは下記。

github.com

Vue.jsとかSVG周りの勉強がてらなんか作るかーと思って作ってみた。
時間管理マトリックスってなんぞや?って人は下記を参照されたし。

www.franklinplanner.co.jp

概要

f:id:igatea:20180307160457p:plain

左下に入力項目の表示非表示ボタンがある。
ボタンを押すと左上に可変の入力欄があり、そこに項目名を入力、重要度と緊急度を数値の入力欄かスライダーで変更できるようにしている。
各値が変更されればそれに合わせてSVGのtext要素の値、座標も変更するといった感じだ。
今はLocalStorageに変更した値を保存するようにしているので再度開きなおしてもそのまま前回の画面のまま編集できるようにしている。

見た目はもっと良くしたいなーと思いながらも今の優先順位的にそこまで入れ込む気はないので手は付けず。

ぶつかった問題とかTipsとか

初めてGithub Pages使ってみた!

リポジトリのSettingsからGitHub PagesのSourceを選択するだけでページを公開することが出来て便利。
基本的にはmasterブランチのファイルが公開されるが変更する方法もあるっぽい?(ここよく分かってない)

masterブランチにビルド後のJSファイルも含める形になる。
仕方ないとは思うけど何かいい方法がないかな。

あとmasterにマージしてからファイルが反映されるまで少し時間がかかる模様。
体感数分。

スプレッド演算子がSyntaxErrorになる

VuexのVueコンポーネントへのマッピング時の...mapState等がSyntaxErrorになった。
最終的にoptions取り除いて.babelrcを作成した。

// before
{
    loader: "babel-loader",
    options: {
        presets: [
            ['env', {'modules': false}]
        ]
    }
}

// after
{
    loader: "babel-loader",
}
{
  "presets": ["es2015"],
  "plugins": ["transform-object-rest-spread"]
}

webpack4のモード

webpack4からはmodeを指定することが出来るようになっていて、そこで開発用かプロダクション用か切り替えることが出来る。
もちろんwebpack.config.jsにmodeを追加することも出来るがwebpackコマンドの引数に追加することも出来る。
なので、下記のように指定してあげるとnpm run ***で使い分けが出来て便利。

"scripts": {
  "dev": "webpack --mode development",
  "build": "webpack --mode production",
}

LocalStorage

Local Storageには文字列で登録されるので、そのままオブジェクトを突っ込むと[object Object]となってしまう。

const obj = {x: 1, y: 2};
localStorage.setItem('items', obj);

localStorage.getItem('items');
// [object Object]

なので適宜、設定時と取得時にJSONの変換を行う必要がある。

// 設定時
const obj = {x: 1, y: 2};
localStorage.setItem('items', JSON.stringify(obj));

// 取得時
JSON.parse(localStorage.getItem('items'));
// {"x":1,"y":2}

Vue.js、Vuex

Vue.jsのwatch

監視する値が何回層かの配列やオブジェクトだったときにウォッチャではdeepというプロパティを定義してtrueにすると内部の値も監視対象としてくれます。

data() {
    return {
        items: [
            {x: 0, y:0},
        ],
    };
},
// 内部監視あり
watch: {
    items: {
        handler() {
            // 処理
        },
        deep: true,
    }
}

// 内部監視なし
watch: {
    items() {
        // 処理
    },
}
SVGの描画時マウントされていないために参照できない問題。

jp.vuejs.org

ref の登録タイミングに関する重要な注意事項として、参照自体は、render 関数の結果として作成されているため、最初の描画においてそれらにアクセスすることができません。それらはまだ存在しておらず、$refs はリアクティブではなく、従ってデータバインディングのためにテンプレートでそれを使用すべきではありません。

地味に躓いた。
text要素の幅を取得して、背景にその幅分のrect要素を広げたかったのだけど、うまくいかなかった。

最終的にはVueのmouted()でフラグを有効にし、それの真偽で処理をするようにした。

data() {
    return {
        isMounted: false,
    };
},
mounted() {
    this.isMounted = true;
},

// ~~~~~~~~ //

if (this.isMounted) {
    // 特定要素の幅取ったり
}
Vuexの各アクションなどのキー名

ミューテーション · Vuex

Vuexでミューテーションやアクションのキーに定数を使用することを提案している箇所がある。
これは本当に好みの問題かもしれない。
一応使って実装してみた。
こんな感じ。

// types.js
export const set    = 'set';

// mutations.js
import * as types from './types';

export default {
    [types.set](state, items) {
        state.items = items;
    }
}

// app.vue
this.$store.commit(types.set, items);

// 文字列のままだと
this.$store.commit('set', items);

定義名はmutationとaction、getterに適用。
gettersはプロパティに生えるから使わなくてもいいかもしれない。

 this.$store.getters[types.initialItems];
 this.$store.getters.initialItems;
VuexのmapStateとmapGettersを産出プロパティに

通常産出プロパティにスプレッド演算子の関係でmapStateとmapGettersは設定できないんだけど無理やりやってみた。
同じキー名のプロパティがあった場合、後方の値で上書きされるので注意。

computed: Object.assign(mapState([
    'items',
    ]), {
        ...mapGetters([
            types.urgentPosition,
            types.importantPosition,
        ]),
    }),
}

これからやってみたいこと

このアプリは遊びで試してみたかったのでそんな時間をかけるつもりはないもののやりたことは色々ある。

  • 文字が枠外に出たりするのでちゃんと文字列が枠内に収まるように
  • 型の導入
  • LocalStorage以外にサーバーと連携してDBに保存するとか
  • なんかもっとかっこいい見た目にしたい!!!

ぶっちゃけ見た目や使い勝手悪すぎて自分のUI周りの実装力の低さを思い知ってしまった。
ここはこれからどれだけ勉強するか悩みどころ。

今までの参加した勉強会のメモを公開した

タイトルの通り。

とあるところでキャリアの成長に関してもっと情報公開して恥をかいていこうよということを言われ、まずは今まで参加した勉強会のメモとかを公開していくことから始めようと思った次第。
かなり雑な部分もあるがそこらへん指摘貰えれば直していきます。
まとめ終わったので再度公開します。

まとめてみて分かったが熱量のあるものとないものでメモの質に大きく差があるなあと思った。
これからは公開することも意識してメモの質を上げたい。

2018年の目標

2018年に入って早2カ月。
今更ですが今年の目標を考えたいなーと。

なんで今更?

実は年末年始の時からこの時期だと思ってた。
そう、転職先が決まった時だ。

無事、4カ月という長い無職期間を経て転職先を決めた。
年末年始、人々が目標を書いているのを横目に僕は転職先が決まったら書こうと思ってた。

理由としては、転職先によって達成したい目標、達成しやすさって変わると思う。
それは事業的なミッションだったり、技術的な成長だったり、個人の趣味や人生についてだったり。
職場によってそれを達成する土壌があったり色々な要素が絡み合った上で目標を決めようと思ってた。

目標

  • 一週間に一回は技術系記事を書く
  • 二カ月に一回は登壇
  • Microsoft MVPを受賞する
  • TOIEC 600点

一週間に一回は技術系記事を書く

一週間仕事なり趣味で開発していれば気づきやつまずいたりしたときの対処など書くことはあるだろう。
無ければ技術的なことが出来ていない可能性が高い。
そういう自戒も込めつつ一週間に一回は記事を書けるように励みたい。

二カ月に一回は登壇

アウトプットの機会を増やしたい。
これは前述の記事と同様に気づきなどの棚卸の面と、記事を書く技術とは別の発表技術を学んでいきたい面もある。
ある程度露出を増やしつつ技術的に人に触れ合う機会も作りたいという面もある。

あと今まで登壇をしたことはあったけど身内に近いコミュニティや初心者向けが多かった。
なのでカンファレンスなどに登壇も目指していきたい。

Microsoft MVPを受賞する

これは前述の二つのアウトプットを継続的に行って目指していきたい。
Microsoft MVPとはいわゆる技術発信を行ってる人に対する表彰制度みたいなものである。
自薦他薦問わずエントリーでき、受賞すればMicrosoftから特定のソフトの提供や限定イベントへの参加権などを特典として貰える。
気になったらググってほしい。
特典が目的というわけではないが一つのアウトプットしていった結果としての目標としたいと思う。

TOIEC 600点

これは個人的なコンプレックス。
エンジニアでありながら英語が全くできないのでこれを克服していきたい。

全くできないというのは具体的にどんなレベルかというと、2015年12月に受験したときのスコアは355点である。
本当に大学を卒業しているんだろうか。僕のキャンパスライフは夢だったのかもしれない。
英語のページを見るときには常にGoogle翻訳を横に並べている。
エンジニアとしては英語で書かれた第一ソースを読めるか読めないかは成長に大きく変わってくる。
ここは努力していきたい。

最後に

目標立ててみた。
年末だけじゃなくて時折見返してうまく達成していこうと思う。
転職したばかりは忙しくて大変そうだが頑張っていこう。

Webpack4ではCLIが切り離された

Webpackの4からCLIが別に切り出された。
なのでそれ以前のWebpackと同じように実行するとエラーが発生する。

> [project name]@1.0.0 dev [working directory]
> webpack

The CLI moved into a separate package: webpack-cli.
Please install 'webpack-cli' in addition to webpack itself to use the CLI.
-> When using npm: npm install webpack-cli -D
-> When using yarn: yarn add webpack-cli -D
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! time-management-matrix@1.0.0 dev: `webpack`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the time-management-matrix@1.0.0 dev script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\[user name]\AppData\Roaming\npm-cache\_logs\2018-02-28T18_56_30_320Z-debug.log

github.com

言われた通りインストールしてみる。

 npm install webpack-cli -D

ちなみに-Dは--save-devらしい。
npm installのhelpに出てこないので知らんかった。

これでまたwebpackコマンドを打つとビルドが実行できるようになる。

Swagger EditorとSwagger UIをDockerで動かす

Swagger Editor

docker pull swaggerapi/swagger-editor
docker run -d -p 81:8080 --name swe swaggerapi/swagger-editor

一部generator.swagger.ioから外部リソースを取得してるみたい。
初期表示のAPI仕様は外部から取得したファイルを表示しているよう。

github.com

今のSwagger Editorはここら辺を変更できなくて、後述のSwagger UIだと変更できるようだ。

Swagger UI

docker pull swaggerapi/swagger-ui
docker run -d -p 82:8080 --name swu swaggerapi/swagger-ui

中身を見ているとDocker起動時に環境変数を設定することで一部パラメータを変更できるようになっている。
例えば下記のようにAPI_URLを設定することで表示に使用するJSONを変更したりできる。

docker run -d -p 82:8080 --name swu -e API_URL=http://generator.swagger.io/api/swagger.json swaggerapi/swagger-ui

2018/02/21現在での最新コミットではポートやOAUTH関係の環境変数が設定できるようになっている。

Dockerfile

Docker使用時に走るdocker-run.shというファイルで環境変数を使った設定を行っている。 この環境変数に関するドキュメントがどこかにあれば教えてほしい。

docker-run.sh

こんな風にSWAGGER_JSONという環境変数にコンテナ内で存在するファイル名を指定してあげるとそれをSwager UIに表示することができる。

docker run -d -p 82:8080 --name swu -e "SWAGGER_JSON=/test.json" -v d:/Docker/swagger/test.json:/test.json swaggerapi/swagger-ui

docker-compose

docker-composeだとこんな感じ。

  swagger-editor:
    image: swaggerapi/swagger-editor
    container_name: "xxx-swagger-editor"
    ports:
      - "8081:8080"

  swagger-ui:
    image: swaggerapi/swagger-ui
    container_name: "xxx-swagger-ui"
    ports:
      - "8082:8080"
    volumes:
      - ./swagger/test.json:/test.json
    environment:
      SWAGGER_JSON: /test.json

ElectronをWindowsのBash(WSL)で試してみて成功しなかった

毎度毎度の失敗談。
Electronを試してみたいと思って、可能ならばWindowのBashとして機能するWindows Subsystem for Linux上で実行したいと思って試してみた。
結局動かなかったけど。
詳しい方がいたら情報求む。
一応記録として残しておく。

まずは公式サイトのクイックスタートを試してみる

そもそもNode.jsが入っていなかったのでインストール

$ sudo apt-get install -y nodejs npm

Node.jsのバージョン管理ツールであるnを使ってみます。

$ sudo npm install -g n

実行する前にBashを一度閉じて再起動しておきます。
そうしないとエラーが発生しました。

$ sudo n stable

     install : node-v9.4.0
       mkdir : /usr/local/n/versions/node/9.4.0
       fetch : https://nodejs.org/dist/v9.4.0/node-v9.4.0-linux-x64.tar.gz
######################################################################## 100.0%
   installed : v9.4.0
$ node -v
v9.4.0
$ which node
/usr/local/bin/node
$ npm -v
5.6.0
$ which npm
/usr/local/bin/npm
$

apt-getでインストールしたNode.jsとnpmは削除しておく。

$ sudo apt-get purge nodejs npm

Electronのサンプルアプリをcloneして実行してみる。

$  git clone https://github.com/electron/electron-quick-start
$ npm install && npm start

> electron@1.7.12 postinstall /mnt/d/Programming/JavaScript/electron-quick-start/node_modules/electron
> node install.js

npm notice created a lockfile as package-lock.json. You should commit this file.
added 152 packages in 43.837s

> electron-quick-start@1.0.0 start /mnt/d/Programming/JavaScript/electron-quick-start
> electron .

/mnt/d/Programming/JavaScript/electron-quick-start/node_modules/electron/dist/electron: error while loading shared libraries: libgtk-x11-2.0.so.0: cannot open shared object file: No such file or directory
npm ERR! file sh
npm ERR! code ELIFECYCLE
npm ERR! errno ENOENT
npm ERR! syscall spawn
npm ERR! electron-quick-start@1.0.0 start: `electron .`
npm ERR! spawn ENOENT
npm ERR!
npm ERR! Failed at the electron-quick-start@1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/iganin/.npm/_logs/2018-02-10T14_29_04_074Z-debug.log

エラーが発生して実行が出来なかった。
ここからは延々と依存関係にあるパッケージをインストールしていくだけで、結局成功していないので注意

libgtk-x11-2.0.so.0: cannot open shared object file: No such file or directoryとあるのでインストールしてみるとエラーが変わった。

$ sudo apt-get install libgtkextra-dev

こんな感じで一つ一つ毎回エラーが変わって依存パッケージがないと出るのでそれが消えるまでインストールしていった。

存在しないと言われるファイル インストールしたパッケージ名
libX11-xcb.so.1 libx11-xcb-dev
libXtst.so.6 libxtst6
libXss.so.1 libxss1
libgconf-2.so.4 libgconf-2-4
libnss3.so libnss3-dev
libasound.so.2 libasound2

一部参考

github.com

上記をインストールしていったらエラーが出るがエラー詳細が出なくなり困った。

$ npm start

> electron-quick-start@1.0.0 start /mnt/d/Programming/JavaScript/electron-quick-start
> electron .

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! electron-quick-start@1.0.0 start: `electron .`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the electron-quick-start@1.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/iganin/.npm/_logs/2018-02-10T14_59_57_523Z-debug.log

もうお手上げ状態。
下記のような記事を挙げている人がいて、上記のエラーと同等かは分からないが動作するようになっているらしい。

grugrut.hatenablog.jp

一度グローバルにElectronを入れてみる

一度グローバルにElectronコマンドをインストールしてそちらを叩けるか試してみた。

sudo npm install -g electron
$ sudo npm install -g electron
[sudo] password for iganin:
/usr/local/bin/electron -> /usr/local/lib/node_modules/electron/cli.js

> electron@1.8.2 postinstall /usr/local/lib/node_modules/electron
> node install.js

/usr/local/lib/node_modules/electron/install.js:47
  throw err
  ^

Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/electron/.electron'
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! electron@1.8.2 postinstall: `node install.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the electron@1.8.2 postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/iganin/.npm/_logs/2018-02-10T15_29_31_278Z-debug.log

エラーが発生した

sudo npm install -g electron --unsafe-perm=true --allow-root

これでインストールは出来た。
けどコマンドを実行しても何も表示されないという状況で謎。

結局

Windowsは難しい。
今度はWindows自体(Powershellとか)で実行できないか試してみようと思う。
WSLの問題なのかElectronの問題なのか・・・。
Windows関係、毎回失敗を繰り返しすぎて心が強くなっていくのを感じる。