dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

VSCodeVimでxやsでコピー(ヤンク)しないようにする

メモ。

素の Vim ではこちらの記事を参考に xs で1文字削除したときにクリップボードにコピーされないようにしていて、

VSCodeVim でも同様の設定をしたい。


方法

settings.json (コマンドパレットの Preferences: Open Settings (JSON)) を開き、以下を追記する。

"vim.normalModeKeyBindings": [
  {
    "before": ["x"],
    "after": ["\"", "_", "x"]
  },
  {
    "before": ["s"],
    "after": ["\"", "_", "s"]
  }
]

ESLintとPrettierを併用するときの設定(eslint-plugin-prettier, eslint-config-prettier)

今さらだけどメモ。
ESLint を使っているプロジェクトに Prettier を導入するときの設定方法。

結論としては、公式のこのページに全部まとまってた。

なお、 prettier-eslint というのもあるようだが調べていない。


先にまとめ

  1. eslint-plugin-prettier: ESLint と一緒に Prettier のチェックをしたい場合に導入する
  2. eslint-config-prettier: Prettier とバッティングする、ESLint のフォーマット関係のルールを無効化する
  3. 1, 2 両方やりたい場合、両方インストールして ESLint の設定に "extends": ["plugin:prettier/recommended"] と書けば OK

eslint-plugin-prettiereslint-config-prettier も公式のパッケージ。


1. eslint-plugin-prettier: ESLint と一緒に Prettier のチェックをしたい場合に導入する

eslintprettier コマンドを別々に実行するのではなく、ESLint で Prettier のチェックも同時にしたい場合に導入する。

$ yarn add --dev prettier eslint-plugin-prettier

ESLint の設定 ( .eslintrc.json ) には以下のように書く。

{
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": "error"
  }
}

// main.js
const a = 1
var b = "foo";
let c = function() {};


console.log(b);

結果

# eslint-config-standard を extends してるとする
$ ./node_modules/.bin/eslint main.js
/Users/yamazaki/workspace/eslint-prettier-playground/main.js
  1:7   error  'a' is assigned a value but never used        no-unused-vars
  1:12  error  Insert `;`                                    prettier/prettier
  2:9   error  Strings must use singlequote                  quotes
  2:14  error  Extra semicolon                               semi
  3:5   error  'c' is assigned a value but never used        no-unused-vars
  3:5   error  'c' is never reassigned. Use 'const' instead  prefer-const
  3:17  error  Missing space before function parentheses     space-before-function-paren
  3:22  error  Extra semicolon                               semi
  3:23  error  Delete `⏎`                                    prettier/prettier
  4:1   error  More than 1 blank line not allowed            no-multiple-empty-lines
  6:15  error  Extra semicolon                               semi

Prettier でフォーマットされる箇所が ESLint の1ルールとして検出されている。
また

https://github.com/prettier/eslint-plugin-prettier

The rule is autofixable -- if you run eslint with the --fix flag, your code will be formatted according to prettier style.

なので、--fix オプションつきで実行することによりフォーマットしてファイルを上書きすることも可能。


2. eslint-config-prettier: Prettier とバッティングする、ESLint のフォーマット関係のルールを無効化する

先の例で、セミコロンの有り無しは eslint-config-standard の設定と Prettier のデフォルト設定がコンフリクトしている。
このように ESLint のフォーマット系ルールは Prettier とコンフリクトする可能性があるので、それらのルールを無効化するために導入するのが eslint-config-prettier

$ yarn add --dev eslint-config-prettier

ESLint の設定 ( .eslintrc.json ) には以下のように書く。

{
  "extends": ["prettier"]
}

なお、

https://github.com/prettier/eslint-config-prettier#installation

Then, add eslint-config-prettier to the "extends" array in your .eslintrc.* file. Make sure to put it last, so it gets the chance to override other configs.

とあるので、extends に複数の config を指定する場合は一番最後に設定する。

// .eslintrc.json
{
  "extends": ["standard", "prettier"]
}

先ほどの main.js に対して

$ ./node_modules/.bin/eslint main.js
/Users/yamazaki/workspace/eslint-prettier-playground/main.js
  1:7  error  'a' is assigned a value but never used  no-unused-vars
  3:5  error  'c' is assigned a value but never used  no-unused-vars

フォーマット系のエラーは出なくなった。
ただし、全部無効化しているだけで Prettier のチェックもしていないので、 --fix オプションをつけただけでは何も起きない。
(別途 prettier --write をすればフォーマットされる)


注意 (2019/03/16追記)

https://github.com/prettier/eslint-config-prettier#special-rules によると、いくつか理由があって無効にしているルールがあるらしく、必要なオプション含めて各自判断しながら有効化しないといけないものがあるらしい。


注意2 (2019/03/17追記)

https://github.com/prettier/eslint-config-prettier#installation
をちゃんと読むと、

If you extend a config which uses a plugin, it is recommended to add "prettier/that-plugin" (if available). For example, eslint-config-airbnb enables eslint-plugin-react rules, so "prettier/react" is needed:

とあるので、 eslint-plugin-xxx を入れている場合は (あれば) 対応する prettier/xxxextends に追加すると
そのプラグインに含まれるフォーマット系のルールを無効化してくれる。

{
  "extends": [
    "airbnb",
    "prettier",
    "prettier/react"
  ]
}


3. 1, 2 両方やりたい場合

Use Both セクションに書かれている通りだが、1, 2どちらも有効にしたい場合は
それぞれの設定を書く必要はなく、 "extends": ["plugin:prettier/recommended"] と書けば OK。

// .eslintrc.json
{
  "extends": ["plugin:prettier/recommended"]
}

eslint-plugin-prettier , eslint-config-prettier どちらも npm install / yarn add しておく必要があることに注意。


注意 (2019/03/17追記)

eslint-config-prettier のところで書いた、eslint-plugin-xxx に対応する prettier/xxx については

// .eslintrc.json
{
  "extends": [
    "plugin:prettier/recommended",
    "prettier/react"
  ]
}

というように書くとうまく効いてるように見えた。
(動作確認したが公式ドキュメントからは見つからず)


その他

これらの設定をしても、 rules: { ... } のところに個別にフォーマット系ルールを設定していた場合はそっちが勝つので注意。当たり前だけど。

「よくわかるWeb Components」を読んだ

Web Components を学ぶべく、昨年の 技術書典5 で販売されていた 1000ch さんの本を買って読んでみました。

2時間程度で読み切れるので、Web Components 全く知らない状態から概要を理解するのにはとても良い本だと思います。
自分は Web Components がどういうものかぐらいは知っている状態で読んだけど、第1章で Web Components を採用するメリットや構成技術について再確認できたし、続く第2章以降で実際のコードを見ながら学べたのはよかったです。

そして、この本を読んだ後に昨年の HTML5 Conference 2018 のこのスライドを見返すとより一層理解が深まりました。
(Conference 当日にセッションを聴いていたが、そのときはほとんど理解できてなかった)

コードを写経したものは↓にあげておきます。


本書で学べること

  • Web Components およびそれらを構成する Cutome Elements、Shadow DOM、ES Modules とはどういう技術か
  • 実際に生のJavaScriptで Web Components を書くとどんな感じか
  • 名前しか知らなかった lit-html がどんな役割を果たしているのか


次に勉強するなら

最近リリースされた Ionic 4 が、Angular 以外の UI ライブラリもサポートするために Web Components で実装したみたいな話を聞いて、そしてそれには Stencil.js という TS + JSX で Web Components 作れるライブラリを使用してるらしいので気になっています。

参考:Introducing Ionic 4: Ionic for Everyone | The Ionic Blog

あとは https://www.webcomponents.org/コンポーネントのサンプルを眺めてみるとか。


以下、学習メモ


第1章

  • Web Components とは
    • 部品の本質的な再利用を、web標準技術で可能にする概念
  • メリット
    • ブラウザネイティブで動作する
    • ツールやライブラリに依存しない
    • 既存プロジェクトの技術と競合しにくい(ReactなどのUIライブラリと共存できる)
    • Shadow DOMによる本質的なスコープ
  • 構成技術
    • Custom Elements
    • Shadow DOM
    • ES Modules


第3章

  • 3.2 attachShadow() できるDOM要素は限定されている
  • 3.4 <slot> 要素を使うと、ホスト要素の子要素をShadow DOM内に挿入できる
<div>
  #shadow-root
    <slot><!-- ここには2つの<p>が入る --></slot>
    <slot name="foo"><!-- ここには<button>が入る --></slot>

  <p>Inserted into default slot</p>
  <p>Also inserted into default slot</p>
  <button slot="foo">Inserted into slot[name=foo]</button>
</div>


第4章

  • 4.4 <script nomodule src=...> とすると、ES Modulesに対応していない環境でのみスクリプトが読み込まれる
    • <script type="module"> と併用できる


第5章

  • 5.3 lit-html
    • Polymer チームが開発
    • 仮想DOMのような仕組みを使って効率よくDOMを更新できる
    • html`<div>...` でテンプレートを記述し
    • render(this.template, this.shadowRoot) で render する

「モブプログラミング体験会 with Chris Lucian」に行ってきた

今日はこちらのイベントに参加してきました。

きっかけはこちらのツイートが TL に流れてきたのがたまたま目に留まって。

行きたかった Regional Scrum Gathering Tokyo 2019 の基調講演に登壇された方からモブプロを学べるってすごいイベントなのでは?と思ったのと、
ちょうど職場環境が変わって業務でモブをがっつりやることになったので、何か持ち帰れるものがあればと思い参加しました。

Twitterハッシュタグ#MobExperiment


私のモブプログラミング経験

先月サイボウズという会社に転職して、そこで初めてモブプロというのを経験しました。
私が所属する kintone チームでは現在、基本的に業務はすべてモブで進めるというスタイルをとっています。
kintone という1つのプロダクトに対してのプロダクトバックログが1つあり、そのバックログを共有する 3~4 名のモブチームが複数存在するという形です。

(ちょうどそんな話を弊社の @ama_ch さんが RSGT2019 で話してました: チームワークの会社で最高のプロダクトを目指すチームができるまで / RSGT2019 - Speaker Deck )

1ヶ月ほど経ってようやくモブで進めることに慣れてきました。
雑多な感想として、私のような新規メンバーのオンボーディングとしてモブは非常に強力だと思います。
既存コードの読み進め方や不慣れな技術スタックがある中で、一人で試行錯誤するのに比べて圧倒的に効率よく知識のキャッチアップができていると感じます。

一方で、以下のようなモヤモヤというか、「こういうときどう対処するのがいいんだろう?」みたいな疑問も生じ始めているところでした。

  • 終日モブで一人で考える/調べる/学ぶ時間が無い
    • 9:45 のデイリーから始まって 18:00 頃まで基本モブ(MTG などの予定がない限り)
    • モブの中で生じた、もう少し知識を深めておきたい/周辺のコードも理解しておきたい みたいなことはモブ終了後になりがち
    • 自分はそういう自己研鑽が業務外になることを良しとしてしまってる人間なので問題だと思ってないが、次に入ってきたメンバーに同じような考えを強制したくはないなあみたいな気持ち
    • ※ それでも 18:00 にはだいたい終わりにしてるから、30 分ぐらいは毎日確保できてる計算になる
  • モブに決まったタイムボックスがない
    • 午前はなんとなく 12:00 の昼休憩までで1つの区切りになるが、午後はドライバーの交代や休憩のタイミングがまちまち
    • 個人でタスクを進めてたときにポモドーロを取り入れてたこともあって、個人的には1コマ○分とかあった方がリズムができていい
    • タイムボックスとかないのが一般的?
  • 次スプリント以降のバックログに対する技術調査を誰が・いつするのか
    • バックログリファインメントで Ready とは言ったものの、「○○する方法については技術調査必要だよね」とか「実際どこ直せばいいのかは事前に軽く調べといた方がいいよね」みたいな状況に何度か遭遇した
    • そういった時間をどこで確保すればいいのか
    • モブの途中に内職することもできそうだが、それだとモブに参加してる意味がないし一人だけ隠れて悪いことをしてるようで誠実ではない
  • 自分がドライバー以外のときにモブに貢献できてないことがある
    • みんなが議論している以前のところでつまずいてることがあり、沈黙状態になる
    • ※これは完全に自分が悪いと思っている。メンバーとしての質問責任を果たしていない


勉強会の内容

午前パートは Chris さんからのプレゼン形式。
前半モブプロとは何かという基本的な話、 Chris さんの所属する Hunbter Industriesでのモブプロやそれ以外のふりかえり・テストなどについてのプラクティスなどを教えていただきました。

ツイートされてたので後で観ましたが、 Chris さんの会社の雰囲気はこの動画がとても参考になります。

ランチをはさんで午後は実際にモブプロを経験。
参加者を2チームに分けて即席チームを作り、お題に取り組みました。


午前パートのメモ

Chris さんの所属している会社でのプラクティスをかなり具体的に説明してくださったんですが、いかんせん自分の英語力が低く理解できなかった部分も多かった...
(これは今回の反省点で、話さえぎってでも都度都度自分の理解が合ってるか確認すべきでした)

その中でも印象に残っていることを。


モブプログラミング RPG

モブするときの役割を RPG っぽく定義したもので、GitHub で公開されてます。
https://github.com/willemlarsen/mobprogrammingrpg

ドライバー以外はみんなナビゲーターかと思ってましたが、こんなにあります。

f:id:dackdive:20190113025313p:plain

(https://github.com/willemlarsen/mobprogrammingrpg/blob/master/Mob%20Gallery.pdf)

そしてモブを RPG とみなして、自分が今何のロールを演じているかはっきりさせることで、自分がモブの中で果たすべき役目が明確になりますね。

ここにある全ロールはこれからじっくり見ていこうと思いますが、個人的になるほどと思ったのが Researcher というロール。

f:id:dackdive:20190113025628p:plain

(https://github.com/willemlarsen/mobprogrammingrpg/blob/master/Researcher.pdf)

今、あるいはこれから必要になる技術調査をモブと並行して進めるロールだという理解です。
冒頭のモヤモヤに対する1つの解になってる気がします。「今から Researcher のロールやります」と言えばモブの議論から抜けることに抵抗がなくなりそうです。


Mob Timer(と、ふりかえりのタイミング)

モブプログラミング時に使えるタイマーアプリで、これも GitHub にあります。
https://github.com/MobProgramming/MobTimer.Python

f:id:dackdive:20190113030410p:plain

モブのメンバーを追加(タイマー下の左側のブロック)してタイマーをセットすると、時間が来たらスクリーンがロックされ、次のドライバーに交代を促されるらしいです。
Chris さんの会社では 1 コマ 45 分でやってると言ってました。

また、面白いなと思ったのはここのメンバーに「Retro」というのを追加して、1 周したタイミングで 45 分のふりかえりを実施するというもの。
(すべてのモブチームで統一してるわけではないよ、と言ってた気がしますが)


Learning Sessions(学習セッション)

Chris さんの会社では毎日1時間 (金曜は2時間) を学習(実験)のための時間として確保しているそうです。

チームで勉強時間と聞くと準備が必要な勉強会形式を想像しますが、一人でもくもくと調べるような時間も含まれているとのこと。
何をやるか、一人でやるか複数でやるか、はそのときそのときで変わるそうです。
(勉強会開くとして、準備の時間もこの枠で確保されてるみたいなイメージかな)


No Estimate

これはアジャイルや Chris さんの会社のことを知ってる人からすれば有名な話のようでしたが、個人的には衝撃でした。
見積もりをしないらしいです。ストーリーポイント使ってない。

その理由のところがうまく聞き取れず残念でしたが、ランチの最中にその話題に触れて

「僕らは価値ある機能をユーザーに一刻も早くデリバリーすることに重点を置いている。だから、僕らがやってるタスク(スクラムで言うユーザーストーリーのことだと思う)は着手してからリリースされるまで長くても 2 時間ぐらい。15 分ぐらいのもある。仮に T シャツサイズ見積もりしたとして、僕らからすると全部 Small になっちゃうよ」

「作ったものを素早くユーザーに届けて、それが本当に価値があったのかを計測することが重要。だから、あるフィーチャーがリリースされてから実際何%ぐらいのユーザーに使われているのかを計測できるようにしておくのは大事だよね」

といった旨のことをおっしゃってたのが印象的でした。


午後パートのメモ

参加者とチーム組んで、お題「三目並べを実装する」に挑戦しました。

※ ネタばらしをすると、これは「Chris と一緒に記念写真撮ろう!楽しくモブしてるっぽい写真にしよう」と言って撮った写真なので Chris さんがっつり演技入ってます。楽しかったのは本当です。

前半パートの Chris さんの話を参考に、僕らもタイマーでドライバーの交代タイミングを決める&1周したらふりかえることにしたんですが、モノを作るよりもモブでの開発を体験するのが目的なので 1コマ5分という高速サイクルに。

以下感じたことを箇条書きに。

  • とにかく楽しい
    • この勉強会に参加するぐらいの人だから熱量が高かった
  • 物理的にPC共有すると 5 分交代でもスイッチングコストそんなかからない
  • 何かあったときにさっと集合できる&フリーハンドで書ける場があるの強い
    • 業務でリモートでやってると、ここらへんに課題を感じることがある
  • 即席チームでも全然なんとかなる


クロージング

最後は2チームがそれぞれやったこと、感じたことを共有した後、自由な質問タイムに。
冒頭のモヤモヤにあった、モブで沈黙状態になる問題についてはある参加者から

「うちも新人とかがモブに加わった際、わかってないんだけどわかってないと言えず置いてけぼりになるという問題が発生してた。でも「わからないことはわからないと言う」っていうのをチームのグランドルールに設定したところ、それだけでもだいぶ効果があった」

という話を聞いて、あーそっか曖昧にせずチームで合意する・明文化するってだけでも改善されるものだなという学びがありました。


おわりに

熱が冷めないうちに書いてしまおうと思って書いたらまとまりがない長文になってしまいましたが、非常に多くのことを学べた濃い勉強会でした。

スクラムのプラクティスもそうですが、チームの問題はチームによって違うので、よそでうまくいってるプラクティスをただ持ってくるだけではうまくいかないというのは今回もあてはまりそうですが、それでも世界最高レベルでモブプロをうまくやっているチームの話が聞けて自分の引き出しが1つ増えたのは非常に良いことだったと思います。

また今回のイベントの運営側のみなさま、勉強会の最中はそこまで積極的に介入せず参加者に自由にやらせてくれましたが、英語でみんなが困ったときに助け舟を出してくれたりモブの最中は定期的に果物やコーヒーを差し入れたりしてくれて、参加者が気持ちよく過ごせるようにという配慮がとても感じられました。
今回の勉強会を企画・開催してくださったことも含め、本当にありがとうございました!

TODO:あとで読む

Chris さんが所属する Hunter Industries について昨年のアドベントカレンダーに記事があったようなので読む。
モブプログラミングという働き方 #モブプログラミング - ナイスビア珍道記

読書記録アプリを作ってkintoneの基本的な使い方を学ぶ

kintoneの使い方を勉強するのにちょうどいい題材はないかと考えたところ
自分が読んだ/読みたい本を管理するアプリが欲しいなと思っていたので、それを作りながら基本操作を学ぶことにした。


アプリのイメージ

読みたいと思った本や web 上のちょっと長い記事をどんどん登録して、読み途中・完了というステータスを管理するだけのシンプルなアプリ。
ゆくゆくは登録の手間をできるだけ省力化したい(URL 登録したら勝手に書籍タイトルが入る、とか)。
また読みたい本の優先度がころころ変わりそうなので、Jira のバックログみたく気軽に並べ替えられるならそういう機能もほしい。


目的

標準機能として kintone アプリでできることを理解するのが目的で、JS カスタマイズやプラグイン機能は含まない。
またなるべく画面だけ見ながら開発してみて、どこまで直感的に迷わず操作できるか試してみる。
加えて、詰まったときの情報検索の仕方を学ぶ。


作る

アプリにアイコンを設定する
設定 > 一般設定 > アイコンと説明

本棚っぽいアイコンどっかから探してこよう、と思ったら標準でも十分なのがあった。
これにします。

f:id:dackdive:20190111004401p:plain

項目作成

思いつきだが、こんな入力項目を用意する。

項目名 説明 データ型
種別 書籍📕かweb上の記事🔗か ドロップダウン
タイトル 書籍/記事のタイトル 文字列
リンク 書籍/記事へのリンク リンク
ステータス 未読/進行中/完了 を区別したい (後述)
開始日 読み始めた日。
ステータスを未読→進行中に変えたら自動でその日がセットされるとか将来やりたい
日付
完了日 読み終わった日。
こちらもステータスを完了に変えたタイミングで自動的にセットしたい
日付
経過日数 読み始めてから何日経ったか。または読み終わるまでに何日かかったか。
あんまり日が経ってるようだと目立たせたりアラートとばしたりしたい
計算(後述)
カテゴリー 書籍のジャンル。技術系とかビジネス系とか (後述)
メモ 感想など自由記入欄 リッチエディター

特に迷うことなく追加できた。

f:id:dackdive:20190111004452p:plain

ステータスとカテゴリーは項目じゃなくて別の機能を使うことにした。後述する。


経過日数を計算する

計算式で「今日」を使う方法がわからなかったので、とりあえず読み始めから読み終わりまでに何日かかったかだけやった。
日数を出そうとしたが計算結果の値が全然合わなかったのでググった。

よくあるご質問 | 日数の計算はできますか。

なるほど、(60 * 60 * 24) で割るらしい。正しく表示された。


カテゴリーを追加する

項目とは別に、こういった設定があるらしい。

設定 > その他の設定 > カテゴリー

これを使うと、レコード一覧を開いたときに左側にカテゴリー一覧が表示されるようになり、簡単にレコードをフィルターすることができる。

f:id:dackdive:20190111004624p:plain

カテゴリーは階層構造で持てるらしい。また1レコードに複数カテゴリー設定できる。


未読→進行中→完了 というステータス遷移を実現する:プロセス管理

なんらかのアクション実行ボタンを押して現在のステータスを変更する、みたいなのはプロセス管理という機能で実現できそうだ。

設定 > 一般設定 > プロセス管理

設定すると、レコード詳細ページ上部にアクションボタンが表示されるようになる。

f:id:dackdive:20190111005228p:plain


レコード一覧に表示する列を設定する

最後に、レコード一覧ページでの列を設定する。一覧設定からできる。

f:id:dackdive:20190111005406p:plain


できた

というわけで30分ぐらいでできた。

f:id:dackdive:20190111005522p:plain


TODO

発展的なお題として、これをもうちょっと使いやすくするために試してみたいことがいくつか。

  • アクションボタン実行に合わせて開始日・完了日の入力を自動化する
  • 経過日数が一定を超えたレコードはハイライト表示したり通知する
  • URL をリンク項目に入力したら勝手にタイトル補完してくれるようにする
  • ドラッグ&ドロップで行並び替えたい
    • かなり難しそう

「Google API Expertが解説するClosure Libraryプログラミングガイド」を読んだ

業務で Closure Library を使うので読んだ。
正確には、最後まで写経しながら読み進めようと思ったけど第5章あたりで挫折して、第6章以降はさっと目を通す程度になってしまった。

出版されたのが 2010 年とかなり古いが、Closure Library を扱った書籍としてはあとこれぐらいしか見当たらず(こっちは英語)。


事前に学んでいたこと

公式ドキュメントをかいつまんで読んだ程度。


本書で学べること

目次ベースでざっくりまとめておく。
Closure Library の基本的なコンポーネント開発方法と、Closure Compiler と組み合わせてコンパイルするための環境構築あたりに興味があったので
第4章まで読んだ後一旦第9章「Closure Compiler による JavaScript の最適化」を先に読んでから第5章に戻った。


第2章「Closure Library を使ってみよう」

depswriter.py, closurebuilder.py という Closure Library に同梱されているツールの使い方が紹介されていた。
Closure Compiler を使わずに Closure Library をどうアプリに組み込めばいいか知りたかったので、最初に言及されていたのは良かった。


第3章「Closure Library の基礎」、第11章「その他の機能」

Closure Library の豊富な UI コンポーネントや関数・ツール群について紹介がされているが、なにしろ膨大なので熟読して覚えるというよりは必要なときに参照できるようリファレンスとして手元に置いとくと良いなと思った。


第4章「Tiny Word アプリケーション」以降

ここから先は複数の章を通じて Tiny Word というサンプルアプリケーションを開発しながら、Closure Library の使い方を学ぶという構成になっている。
ただし第7章、第8章はアプリとして完成させるために Closure Library とは直接関係ないサーバーサイドの開発 (Google App Engine w/ Python) の話になっている。
一部 Closure Library を使った非同期処理の書き方も含むが、アプリを作りきるのが目的でなければこのへんはスキップしてもいいかも。

サンプルアプリで使用している Closure Library のコンポーネントは、主にこのあたり:

  • データソース ( .goog.ds.JsDataSource ) およびデータマネージャ ( goog.ds.DataManager )
    • 多くの形式のデータを共通のインターフェースで扱える
  • ツールバー、メニュー ( goog.ui.Tab , goog.ui.Menu )
  • ツリーコントロール ( goog.ui.tree.TreeControl )
    • こういうやつ↓

f:id:dackdive:20190109003313p:plain


第9章「Closure Compiler による JavaScript の最適化」

JavaScript の型チェックと最適化を行う Closure Compiler の概要と、closurebuilder.py と組み合わせて使う方法について。

特に

あたり、かなりページを割いて解説されていたのは有難かった。


第10章「デバッグ・テスト」

デバッグツール ( goog.debug , goog.asserts) の使い方、およびテストフレームワーク ( JSUnit ) を使ったテストの書き方。
残念ながらあんまちゃんと読めていない。


本書で学べないこと

  • Closure Template ( .soy ファイル) を使ったコンポーネントの開発方法
    • Soy テンプレートはこの書籍の対象外
  • コンポーネントの使い方 (override しないといけないメソッドなど) をどうやって調べるか
  • Closure Compiler の型チェックでエラーが出たときの原因と対処方法の調べ方
    • 9.3.3 に代表的なエラーをリストアップしてくれているが、ここに書かれていないエラーが発生したときに何が原因で怒られているのかよくわからなかった


その他:2019年にこの本を読む上での注意点

depswriter.py, closurebuilder.py の使い方が学べてよかった、と上に書いたが、書籍が出版された時代から Closure Compiler もいくらか進歩しており
コンパイル方法などは当時とは状況が変わってそう。

というのも、closurebuilder.py でビルドをすると、以下のような警告が出る。

$ python closure-library/closure/bin/build/closurebuilder.py \
  --root=closure-library \
  --root=scripts \
  --namespace="tinyword.App" \
  --output_mode=compiled \
  --compiler_jar=compiler.jar \
  --output_file=script.js
closure-library/closure/bin/build/closurebuilder.py: Scanning paths...
closure-library/closure/bin/build/closurebuilder.py: 1620 sources scanned.
closure-library/closure/bin/build/closurebuilder.py: Building dependency tree..
closure-library/closure/bin/build/closurebuilder.py: Closure Compiler now natively understands and orders Closure dependencies and
is prefererred over using this script for performing JavaScript compilation.

Please migrate your codebase.

See:
https://github.com/google/closure-compiler/wiki/Managing-Dependencies

おそらくだが現在は Closure Compiler 単体で goog.provide() / goog.require() の依存解決はできるみたい。
また Closure Compiler も現在は npm パッケージで公開されているものもある

さらに、こんな記事もある。

今回、自分も写経していてこのへんの開発効率の悪さ(ローカルサーバー立ち上げる、ファイル編集するたび closurebuilder.py 実行して待たされる、etc.)は結構ストレスを感じたので
開発環境まわりはこの後もう少し調べてみたい。

Google Closure CompilerとかGoogle Closure LibraryなどのClosure Tools概要まとめ

Google Closure ○○ シリーズが多くてわからん、となったのでメモ。
主に Closure Compiler と Closure Library を中心に。

総称として Closure Tools と呼ぶらしいです。ここにまとまってます。

またソースコードはすべて GitHub で公開されている模様。

https://github.com/google?utf8=%E2%9C%93&q=closure&type=&language=

Google Closure Compiler

The Closure Compiler is a tool for making JavaScript download and run faster. Instead of compiling from a source language to machine code, it compiles from JavaScript to better JavaScript. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what's left. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls.

JS の型チェックや圧縮、最適化などをやってくれるコンパイラ
半角スペースなどを取り除いたり変数名を省略することで JS を圧縮してくれるのに加え、JSDoc 形式のアノテーションを記述するとコンパイル時に型のチェックなども行ってくれます。

GitHub

https://github.com/google/closure-compiler

インストール方法

いくつか選択肢がある。
(参考: https://developers.google.com/closure/compiler/https://github.com/google/closure-compiler/ の Getting Started)

  1. Java アプリ (.jar) として提供されているものをダウンロードして使う (最新版のダウンロードリンクはこちら)
  2. web アプリが https://closure-compiler.appspot.com/home にあるので、コンパイルしたいコードを貼り付けて web 上でコンパイルする
  3. REST API として提供されているものを使う (参考)
  4. npm パッケージとして提供されているものを使う https://www.npmjs.com/package/google-closure-compiler

その他、Maven のプラグインもある らしいがよくわからない。

使い方

ここでは、4 の npm パッケージを使うものとして進めます。

$ npm install google-closure-compiler

素の ./node_modules/.bin/google-closure-compiler を叩いてもいいですが、オプションとして渡すパラメータもあるので npm script を書いておきます。

"scripts": {
  "build": "google-closure-compiler --js=main.js --js_output_file=build.js"
}

--jsコンパイル対象のファイル、 --js_output_fileコンパイル後の出力先を指定します。

サンプルとなるファイルを書いてみます。

サンプル1 (単純な例)

function hello() {
  alert('hello');
}

結果1 (コンパイル後の JS)

function hello(){alert("hello")};

サンプル2 (アノテーションによる型チェック)

/** @const {number}**/
var foo = 100;

foo = 200;

/** @define {string} **/
var greeting = 'hello';

greeting = 100;

結果2 (ビルド実行時の様子)

$ npm run build
main.js:4: WARNING - constant foo assigned a value more than once.
Original definition at main.js:2
foo = 200;
^^^^^^^^^

main.js:9: WARNING - constant greeting assigned a value more than once.
Original definition at main.js:7
greeting = 100;
^^^^^^^^^^^^^^

0 error(s), 2 warning(s)

error と warning の違いはわかってません。


リファレンス

Google Closure Library

The Closure Library is a broad, well-tested, modular, and cross-browser JavaScript library. You can pull just what you need from a large set of reusable UI widgets and controls, and from lower-level utilities for DOM manipulation, server communication, animation, data structures, unit testing, rich-text editing, and more.

DOM 操作のための API やら豊富な UI コンポーネントやらが含まれているライブラリ。
APIhttps://google.github.io/closure-library/api/ に一覧が載っているが多すぎて全容を把握できない。


GitHub

https://github.com/google/closure-library


インストール方法

GitHub の README を見る限り、こちらも npm でインストールできるようです。

$ npm install google-closure-library


使い方

先ほど npm でインストールできるといったものの、 require() で読み込めるようにするには何らかのビルドツールと組み合わせて使う方法があり、かつ closure compiler でコンパイルする方法がまだよくわかっていないため
リポジトリを手動でクローンしたものを使ってサンプルを書いてみます。

ここの通り。
Getting Started with the Closure Library  |  Closure Library  |  Google Developers

$ git clone https://github.com/google/closure-library

JS (hello.js)

goog.require('goog.dom');
goog.require('goog.dom.TagName');

function sayHi() {
  var newHeader = goog.dom.createDom(goog.dom.TagName.H1, {'style': 'background-color:#EEE'},
    'Hello world!');
  goog.dom.appendChild(document.body, newHeader);
}

HTML

<html>
  <head>
    <script src="closure-library/closure/goog/base.js"></script>
    <script src="hello.js"></script>
  </head>
  <body onload="sayHi()">
  </body>
</html>

結果

f:id:dackdive:20181126165452p:plain

goog.require() で必要なモジュールをインポートして使うのが基本らしい。
注意点として、 goog.require() は指定したモジュールを読み込むための <script> タグをドキュメントに挿入するという挙動になっているので、 goog.require() してるスクリプトとインポートしたモジュールを使用するスクリプトを同じスクリプト内で実行してはいけない。

<script src="closure-library/closure/goog/base.js"></script>
<script>
  // DON'T DO THIS.
  goog.require('goog.dom');
  var newHeader = goog.dom.createDom(goog.dom.TagName.H1);
</script>


リファレンス

Google Closure Templates

Closure Templates is a client-side and server-side templating system used to build dynamic and reusable HTML and UI elements. (中略) It supports Java and JavaScript and uses a language-neutral expression syntax and data model.

テンプレートエンジン。JavaJavaScript もサポートしているとな。


GitHub

https://github.com/google/closure-templates


インストール方法

GitHub の README を見ると、これも npm で提供されてるようです。
https://www.npmjs.com/package/google-closure-templates

ただし上の2つと異なり Getting Started には npm でのインストール方法は記載されていなかったので、標準の導入方法ではない...?


使い方

クライアント側のサンプルとして、
Hello World Using JavaScript  |  Closure Templates  |  Google Developers
を読んでみます。

※なお、サイトから各リンクをクリックすると軒並み 404 になるので、GitHub の README に記載されてるリンクを開いた方がいいです

Closure Library のときと同じく、npm パッケージは使わず
https://dl.google.com/closure-templates/closure-templates-for-javascript-latest.zip から最新版の closure-templates をダウンロードしてそれを使います。

テンプレートファイルの拡張子は .soy らしい。

simple.soy

{namespace examples.simple}

/**
 * Says hello to the world.
 */
{template .helloWorld}
  Hello world!
{/template}

こいつをダウンロードした zip に入っている SoyToJsSrcCompiler.jar というファイルでコンパイルすると JS ファイルが生成されるらしい。

$ java -jar SoyToJsSrcCompiler.jar --outputPathFormat simple.js --srcs simple.soy

これを読み込む HTML ファイル側は

<!DOCTYPE html>
<html>
<head>
  <title>The Hello Wolrd of Closure Templates</title>
  <script src="soyutils.js"></script>
  <script src="simple.js"></script>
</head>
<body>
  <script type="text/javascript">
    // Exercise the .helloWorld template
    document.write(examples.simple.helloWorld());
  </script>
</body>
</html>

結果

f:id:dackdive:20181126183132p:plain


Google Closure Linter

しょっぱなに Closure Linter is deprecated と書いてあるのでスルー。

https://github.com/google/closure-linter

Please note that the closure linter is deprecated. Esp. if you use ES6 features, the tool will not work for you.

Google Closure Stylesheets

CSS を拡張した言語。
公式リファレンスサイトはなく GitHubリポジトリに飛ばされる。


GitHub

https://github.com/google/closure-stylesheets


インストール方法・使い方

jar ファイルをダウンロードしてくる方式。
時間の都合上試してない。

おまけ: ClosureBuilder

これは調べてる過程で発見したもので、上に挙げた Closure Library に含まれるツールの一部っぽいです。
Closure Library のリポジトリ内に closure/bin/build/closurebuilder.py というスクリプトがあります。

The closurebuilder.py tool, located in closure/bin/build, is a tool to help build compiled JavaScript files. It scans your files and the Closure Library files and can calculate orderings of script files in dependency order. It can output either the scripts' filenames or their contents in dependency order, or can pass the files along to the Closure Compiler to produce a compiled version.

JS のコンパイル? Closure Compiler もあるのに?という感じもしますがよくわからない。
むしろ Closure Compiler と併用する場合の実行方法とかまで書かれている。

まとめとよくわからないこと

とりあえず一通り手を動かして試してみました。ソースはここに置いておきます。
https://github.com/zaki-yama/google-closure-tools-sample

各ツールの概要はわかったけど一歩踏み込んだ使い方とかはまだまだですね。

以下、今回だけではわからなかったこと: