Angularでのローカル開発時に便利なProxyConfig

前提条件

ローカル環境での開発時にはMockAPIを返すサーバと実際のAPIサーバの2つを作ることが多い。そして小規模〜中規模のモノリシックなアプリの場合はユーザがアクセスするFQDNAPIFQDNが同じであることも多い。

課題

ただ、実際に開発するときにはAngularはWebpackのDevServerが4200ポートを使っていて、Rails,NodeなどのAPIサーバは他のポートを使わざるを得ない。これまで自分が作ったWebサービスではMockAPIと実際のAPIサーバのアクセスをどう切り替えていたかというと、environment.mock.ts とかのファイルにURLのフルパスを書いていた。npmから起動するときに ng serve -c=mock とかでmockのconfigurationを読むようにしていた。

export const environment = {
  production: false,
  // api server
  api: {
    url: 'http://127.0.0.1:3000/api'
  }
};

最大の問題はブラウザ上に表示されているFQDNAPIサーバのFQDNが異なっていた。可能な限り実際のサーバ構成とローカル開発の環境は同じであるほうがいらないトラブルを減らせる。あとはMock用の設定とローカル開発用のAPIサーバの設定とかで個別でファイルを作っていた。

解決策

https://angular.io/guide/build#proxying-to-a-backend-server に書いてあることがすべて。 proxy.conf.jsonを作ってからangular.jsonに読み込ませることで設定終了という非常にお手軽。

{
  "/api": {
    "target": "http://127.0.0.1:3000",
    "secure": false
  }
}

in-memory-web-apiをつかわないのか?

自分はあまりAngularのチュートリアルでも出てくる GitHub - angular/in-memory-web-api を積極的に導入していない。(社内でやっているところはある) 理由はいくつかあって、

  1. Chrome Dev ToolでもわかるようにHTTPリクエストを走らせたい
  2. 本番でフロントエンドのコードとAPIのコードが別れているのであれば開発時でも別けたいし、開発のためだけにコードを入れると問題の切り分けが面倒
  3. Mockを1つ追加したいだけなのに毎回コンパイル走るのは遅いし、Angularに慣れてない人にもMockは触ってほしいのでAngularをあまり意識させたくない
  4. swaggerや agreed などドキュメント+Mockサーバで管理したほうが便利だと思う(この辺はまだ手を付けれていない)

技術書とか以外で2018年に買ってよかった(気がする)もの

何気なく去年のクレジットカードの利用状況を見てたのでまとめる。

バタフライボードA4

ミーティング行くときには大体携帯している。A4サイズでそこそこ書けるし、複数人でやっててもみんなで書くとかもできて汎用性は高い。Office Lensとの相性もいいので使い勝手はよい。会社のロゴ入りのホワイトボードも買ってもらった。赤字0.5mmのペンも出たので更に嬉しい。ホワイトボードの宿命なのか他のペンで書くとうまく消えなくてそろそろ買い替えたいなぁというお気持ちはある。ホワイトボードにこれを貼ったり、広げてA3ぐらいの大きさにしたりと汎用性は高い

単 −HITOE long wallet

もともと財布の中身を減らしたいなと思っていたので購入。iPhone8の幅より薄くてカード10枚ぐらいは入る。コンビニとかはApplePayでいいけどそれ以外はクレカ/現金が必要なので財布自体はまだまだ持ち歩くことが多い。カバンとかを持ってないときはズボンのポケットに財布をいれるのでズボンの傷み防止にもなってる。デザインもシンプルだしちょうどいい分量が入るので結構重宝してる。多分今の財布が壊れたら同じものを選択すると思う。確かAmazonでも買えるはず。

www.makuake.com

フィリップス ソニッケアー ダイヤモンドクリーン スマート 電動歯ブラシ ルナーブルー HX9964/55

2017年後半から今まで以上に健康に気を使うようになった。3ヶ月ごとに歯医者の定期検診とかにも行ってる。歯ブラシの種類によって自動でコースを設定してくれたりとモノグサな自分にはちょうどいいと思う。スマホアプリと連携しているが洗面台にスマホを持っていく習慣がないのでそこは使ってない。

東京西川エアーSX

朝起きると体が痛いことがしばしば起きててそろそろベッド買い替え時かなーと思っていたところに会社の人と睡眠の話になったので購入。今まではマットレス一体型のベッドだったので、ベッドフレームからまるごと買い替えで結構な出費(Macbook Proが買える値段ぐらい)だった。今までのベッドと違いすぎたため慣れるまでに2週間ぐらいかかったので、買ってしばらくは「いやーこれ失敗したかも」と思っていたが慣れると結構楽な気がする。Mi bandで睡眠時間を図ってみたら、確か深い睡眠が30分ぐらい延びていたはずなので数字にはしっかり出てるし、携帯のバイブ音でも起きれるのが今では起きれないことも増えた(単に歳のせいかもしれないが)。枕も合わせて買い直した。東京西川で軽く図ってもらって購入。一般的に睡眠時間は長いと言われているのでボーナスとかが出てる人は結構早めに投資しても元が取れるかもしれないがものによっては部屋のサイズを圧迫するので注意。

www.airsleep.jp

shop.nishikawasangyo.co.jp

スタバのアンケートの体験がイケてない話

今日スタバに行ったときにレシートを貰ったらアンケートに答えるとドリンク1杯無料というのをやってたのでまぁいいか。とやってみたら体験がよくなかった。

アンケート
スタバのアンケート

手順は

  1. QRコードでアンケートサイトに遷移する ← わかる
  2. ログイン後カスタマー番号 17桁を自分で 入力する。ここで利用規約とか読んでもらう ← えー
  3. アンケートに回答すると 手書きでレシートに引き換え番号を記載して スタバへ行く ← ふぁっ!?
  4. スタバでレシートに記載してあるバーコードをスキャンしてドリンクゲット

いやいやいや... スマホで17桁の番号を入力するなんてないでしょ今頃。間違えるし。更に手書きで番号を記入するって。なぜにこんな体験悪いんだろうなぁ。普通にやるんだったら

  1. QRコードでアンケートサイトに遷移する
  2. ログイン後には入力欄にカスタマー番号がプリセットされている。利用規約とか読んでもらう
  3. アンケートに回答すると引き換え用のバーコードが表示されているので画像を保管する
  4. 保管した画像をスタバでスキャンしてもらってドリンクゲット

これだったらスマホだけで全部完結するし。ペン持ってなくてももう1杯もらえるし楽だと思うんだけど、何かしらのシステム制約があったんだろうなぁ。

今回は体験が悪かったので、最後の自由記入欄で「アンケートの体験が悪かった」と書いてしまったんだけどそういうサービスが結構あるなぁと改めて思った。自分はあまりアンケートに答えたりしないのはそれも1つある。色々CS用の情報欲しいとかあるのはわかるんだけど、そこが悪いとどうしてもサービスを継続して使いたいとか、フィードバックしたいというモチベーションが失われる。ユーザは「まぁアンケートに答えてあげてもいいかなぁ」という感情になりやすいので、きちんとした体験を提供しないと逆効果になってしまうのが残念だ。

とはいえ、明日も同様のことをやっていたら多分答えてしまう。スタバ1杯無料という誘惑は大きいのである

Angularでpugを使ってみた

ng add ng-cli-pug-loader を使えばOK.

github.com

なぜpug?

HTMLをそのまま書くのもいいかなぁと思ったけど、pugで楽にかけないかなと思って使ってみた。

これが

<table class="l-tasks">
  <thead>
  <tr>
    <td></td>
    <td>タイトル</td>
    <td>説明</td>
    <td>期限</td>
    <td>削除</td>
  </tr>
  </thead>
  <tbody>
  <ng-container *ngIf="(tasks$ | async) as t">
    <ng-container *ngIf="t.data.length; else notFound">
      <tr *ngFor="let task of t.data">
        <td class="m-done"><input type="radio"></td>
        <td class="m-title">{{task.title}}</td>
        <td class="m-description">{{task.description}}</td>
        <td class="m-due_date">{{task.due_date}}</td>
        <td class="m-delete">
          <app-button text="削除" (onClick)="delete(task.id)" buttonSize="small" buttonType="danger"></app-button>
        </td>
      </tr>
    </ng-container>
    <ng-template #notFound>
      <td colspan="4" class="no-task-message">data not found</td>
    </ng-template>
  </ng-container>
  </tbody>
</table>

こうなって比較的スッキリ

table.l-tasks
  thead
    tr
      td
      td タイトル
      td 説明
      td 期限
      td 削除
  tbody
    ng-container(*ngIf="(tasks$ | async) as t")
      ng-container(*ngIf="t.data.length; else notFound")
        tr(*ngFor="let task of t.data")
          td.m-done
            input(type="radio")
          td.m-title {{task.title}}
          td.m-description {{task.description}}
          td.m-due_date {{task.due_date}}
          td.m-delete
            app-button(text="削除", (onClick)="delete(task.id)", buttonSize="small", buttonType="danger")
    ng-template(#notFound)
      td.no-task-message(colspan="4") data not found

微妙だったところ

普段開発でIntellij IDEAを使っているが、リファクタリングとかで Find Usage ( option + F7) で使っている変数を探すときが多々あるが、pugにするとそこが動かない。まぁそうだよなぁというのはある。pugの便利機能をどこまで使うか?と言われるとうーん...と悩んでしまうので難しいところ。Angularの記法で書いたほうが健全な気がする

MacVim-kaoriyaでrubyが認識できないときの対応

mojaveのMacをゼロからセットアップしたときにハマった。

なお、使っていたバージョンは MacVim-KaoriYa 20180324

  1. libruby.2.0.0.dylib が見つからないと言われる
  2. CONFIGURE_OPTS="--disable-install-rdoc --enable-shared" rbenv install 2.4.5 として、.vimrcset rubydll=<path> を書いてみる
  3. vimruby print RUBY_VERSION を実行すると、 ライブラリの関数 rb_cFixnum をロードできませんでした と言われる
  4. ググるPatch 8.0.0163 で対応されている模様
  5. brew から入れてみるかーと思い立ったがコンパイルエラーが起きる(下にメモ)
  6. 辛くなってきたので、brew install ruby@2.0 && brew link ruby@2.0 --force で古いRubyを入れる

systemが変わるから正直イヤだけど...他で困ったら考えるか

コンパイルエラー内容

Last 15 lines from /Users/hachi/Library/Logs/Homebrew/macvim-kaoriya/03.make:
   
<長いので中略>
** BUILD FAILED **


The following build commands failed:
    CompileC /tmp/macvim-kaoriya-20181107-81261-1qv228j/src/MacVim/build/MacVim.build/Release/MacVim.build/Objects-normal/x86_64/MMPreferenceController.o /tmp/macvim-kaoriya-20181107-81261-1qv228j/src/MacVim/MMPreferenceController.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler
(1 failure)
make[1]: *** [macvim] Error 65
make: *** [first] Error 2

Rubyで日本のサマータイムを調べてみた

東京オリンピックのためにサマータイムを入れるとかそんなアホな話があったんで、改めてwikipediaを見てたところ、1948年 - 1951年に日本にもサマータイムがあったらしい。

夏時間 - Wikipedia

へーあったんだーと思ってRubyの挙動はどうなっているのかを見てみた。

[48] pry(main)> Date.new(1951, 9, 1).upto(Date.new(1951, 9, 10)){|d| puts "#{d.to_time} -> #{d.to_time.zone}"}
1951-09-01 00:00:00 +1000 -> JDT
1951-09-02 00:00:00 +1000 -> JDT
1951-09-03 00:00:00 +1000 -> JDT
1951-09-04 00:00:00 +1000 -> JDT
1951-09-05 00:00:00 +1000 -> JDT
1951-09-06 00:00:00 +1000 -> JDT
1951-09-07 00:00:00 +1000 -> JDT
1951-09-08 00:00:00 +1000 -> JDT
1951-09-09 00:00:00 +0900 -> JST
1951-09-10 00:00:00 +0900 -> JST


[62] pry(main)> Time.new(1951, 9, 8)
=> 1951-09-08 00:00:00 +1000
[63] pry(main)> Time.new(1951, 9, 8).dst?
=> true

確かにある。Time#dst?true になる。もう少し細かく見ていく。

23時になるとJSTに戻る。サマータイムが終わるときには1時間戻さなきゃいけないからか。

[71] pry(main)> Time.new(1951, 9, 8, 22)
=> 1951-09-08 22:00:00 +1000
[72] pry(main)> Time.new(1951, 9, 8, 23)
=> 1951-09-08 23:00:00 +0900

22時に2時間を足すと23時になってタイムゾーンは戻ってる

[110] pry(main)> Time.new(1951, 9, 8, 22, 59) + (60 * 60 * 1)
=> 1951-09-08 23:59:00 +1000
[111] pry(main)> Time.new(1951, 9, 8, 22, 59) + 60 * 60 * 2
=> 1951-09-08 23:59:00 +0900
[112] pry(main)> Time.new(1951, 9, 8, 22, 59) + 60 * 60 * 3
=> 1951-09-09 00:59:00 +0900

とりあえずいろいろとめんどくさいことはわかった。システム改修だ〜五輪特需だ〜とはしゃいでるクソ営業さん以外は特にメリットないですな

西日本応援プロジェクト 真夏の大LT大会! に参加してきた

techplay.jp

はてな ブログに書くまでがイベントですよ。ということなので書いてみる。実家が九州なので今回の大雨の影響は少なからずあり、東京にいながらできることはなんだろうということで参加してみた。

元来、募金というのが非常に嫌いな人種なので大人になってからはあまりしたことがないが、こういうゆるい感じでできるというのは非常にいいなーと思った。登壇してる方、内容もいろいろとすごくて、インターネットの思い出というお題というこもとあり、笑ってたこともあれば、「あー」「へー」と言ってたこともあるし、非常に多岐にわたっていた。

個人的にはあの徳丸先生と「俺がRailsだ!」の名言を残した kamipo さんを見れたのが非常によかった。藤本さんのインターネットの話はまぁ見に覚えがありすぎて直視できない。笑ってたけど、自分は自分のを掘り返す勇気はない

ということで、主催のそーだいさん、941さんの実行力に最大の賛辞と感謝を送りつつこのブログをしめる。ありがとうございました!!

戦利品