- なぜSPA技術でウェブサイトをつくるのか?
ここ最近、SPAを作るフロントエンドエンジニアを中心に、アプリケーションではないウェブサイトもReactやVueで作る動きが活発になってきました。
そもそもなぜReactやVueを使ってウェブサイトを作るのか?
これらの技術を使うことによって何が解決するのか?
本記事ではそういった問いに対する自分の考えを示します。
SPA以前のウェブサイト制作
注)現在進行系でも非SPAなウェブサイト制作が主流です。
現在主流な制作手法は、WordPressに独自のテーマを実装して制作する方法です。
PHPなどで動的にHTMLを生成し、大きなCSS・JSが一枚というケースが多いです。
もちろん、モダンフロントエンドを取り込んでいる場合もあって、次のような工夫をしていることが多いです。
SCSSのようなメタ言語でCSSを記述し、保守の手間を減らす。
webpackなどのバンドラーを利用する。
ただ、この場合のJSはjQueryが使われることが多く、jQueryプラグインにはnpm経由で利用できないものもあって辛い印象を持っています。
コーポレートサイトやWordPress製のブログといったウェブサイトでは、CDNを利用してファイルを高速で配信しているサイトもありますが、フロントエンドのレンダリングの速さはあまり重視されていないように思えます。
そもそもなぜSPA技術でウェブサイトを?
CSS系の問題を一挙解決
正直のところ、CSSは難しい言語だと思います。
スタイルは子要素へ受け継がれていく、セレクタによる優先度、未使用部分を発見することの困難さなどの原因からCSSは肥大化していきます。
CSS肥大化によって、重複したスタイルが出現して保守が大変になる、ページ読み込み速度が遅くなっていくなどの問題が発生します。
保守が困難という問題に対抗するためにBEM, OOCSS, FLOCSSなどの命名手法が採用するなどの取り組みがあります。ページ読み込みを高速化するには、ページ読み込み時に見える範囲(above-the-fold)のCSSをHTMLに埋め込むの手法が有効です。これらのCSSを検出し、埋め込むためのwebpackプラグインなどが存在しますが、いまいち認知はされていないようです。
一方、React, Vueといったライブラリではコンポーネント内にCSSを書く方法でこれらの問題を避けています。
JSが保守しやすくなる
JavaScriptでDOMにイベントを付与するようなコードが圧倒的にわかりやすくなります。
いわゆる「宣言的」に書けるから嬉しいといった話です。
参考: 宣言的UI - Speaker Deck
DOMを直接触るようなコードでは、他人が書いたコードを読むのがかなりしんどいです。(個人の感想です)設計によって苦しさを緩和することもできますが、記述は圧倒的に増えます。
Before
<div id='app'>
<button id='trigger'>Click!</button>
</div>
<script>
const trigger = document.getElementById('trigger')
trigger.addEventListener('click', () => {
const newEl = document.createElement('div')
newEl.textContent = 'hello world'
document.getElementById('app').appendChild(newEl)
newEl.addEventListener('click', onClickHoge)
})
After
const App = () => {
const [isActive, setActive] = useState(false)
const onClickButton = useCallback(() => setActive(true), [])
const onClickHoge = useCallback(() => {}, [])
return <div>
<button onClick={onClickButton}>Click</button>
{isActive && <div onClick={onClickHoge}>Hello World</div>}
</div>
}
ライブラリ管理の話
jQuery系のプラグインはパッケージマネージャで使えない場合があり、そういった場合minfyされたJSファイルをプロジェクト中に置くことになるでしょう。
開発者や環境にもよりますが、バージョンアップがされづらく、最悪の場合ソースが直接書き換えられるという問題もあります。(実際に経験があります。)また、バージョンアップされないライブラリのために、jQuery本体のバージョンもあげられないというケースも存在します。
ReactやVueの開発ではnpmがほぼ必須といってもいい環境なので、今どのバージョンが使われているかははっきりわかりますし、(よっぽどのことがない限り)直接ソースが書き換えられることはないでしょう。
バージョンアップには手間はかかりますが、パッケージマネージャがない状況と比べれば圧倒的に楽です。
素直にSPA開発で発達した開発手法に乗っかりましょう。
DX系・環境構築の話
サイトを制作する際に、開発環境を構築する必要があります。
サイトを制作する前にgulp、gruntなどといったツールを使って、開発するための環境を整備することが必須とも言える状況でした。また、これらの環境は属人化しやすく他の人が引き継ぎにくいといった課題もありました。
SPA系のフレームワークでは、これらのタスクに加えてJS, CSS系の最適化も自動で行ってくれることが多く、手間なく環境を整えられます。
また、npmで配布されているSPA系のライブラリを簡単に使える、バージョン管理など開発フローに載せやすい、TypeScriptを使って開発するなど開発者として開発しやすい環境を手間なく用意できます。
作って終わりではなくなった
個人の感想に近いですが、近年作って終わりではなく、公開してからも継続して運営するようなものが増えてきたと思います。
つまり、今まではバージョン管理ツールに載せず、汚いコードで乗り切るといったことも可能でした。ただ、これからはWebサービス開発で利用しているような開発手法を利用することが重要だと感じています。
React, Vueを利用する上ではフレームワークを利用することでwebpack, babelといったツールの設定が隠蔽され属人性が減り、規約が存在することで設計のブレを減らせます。
今後はフレームワークという巨人の肩にのり、ウェブサイトを作っていく手法が流行っていくといいと思っています。
まとめ
この記事で示したものはかなり偏った考えかもしれません。WordPressで使いたいテーマがあるということであれば、そちらを利用するといいでしょう。
ただ、自分でしっかりデザインしたい、テーマ以上の品質を保ちたいということであれば、製作者のレベルにもよりますがReact, Vueで作ったほうがよりよいものができると思います。
また、このあとに「なぜReact, Vue単体ではウェブサイト開発が行われないのか」というテーマがあり、サーバーサイドレンダリング(SSR)・静的サイトジェネレーター(SSG)というトピックに派生していきます。
よりよい環境が普及することを願っています。
2019/10/14 - VSCodeの調子が悪い時はVSCode Insidersに避難しよう
私のVSCode遅くない?
自分は普段から『VSCode』(Visual Studio Code)を愛用していて、RubyやPythonなどJavaScript/TypeScript以外の言語を書く時にも利用しています。
しかし、最近VScodeを利用していると重く、コードを書く時のテンションも上がらなくなってしまいました。
何らかの拡張機能が原因だとは思うのですが、すべての拡張機能を確認する気にはなれませんでした。
ただ、VSCode以外のエディタを使うにしても、VSCodeに慣れてしまったため、生産性は大きく落ちてしまいます。
ここ最近VSCodeが重くてしんどい…Vimに戻るのも違う気がする— もっと@技術書典7 お89C (@mottox2) September 27, 2019
選ばれたのは『VSCode Insiders』でした
そこで選んだのが『VSCode Insiders』です。『VSCode Insiders』はVSCodeの開発版ビルドです。私達が普段使っている安定版にリリースされる機能が先行的に使えるものです。
この開発版ビルドのいいところは安定版のVSCodeとは別にインストール出来ることです。拡張機能の設定もおのおのに持っているため、必要なものだけインストールして運用できます。
「開発版なので安定はしてないのでは?」と思われがちですが、今のところ問題なく使えています。変なクラッシュにも遭遇していません。
どういう使い方をしているのか?
ここ最近はJavaScript/TypeScriptを書くときだけ『VSCode Insiders』をメインエディタとして使っています。
そこでどういう方針で使っているのか、使う際に注意する点を説明します。
方針
「快適にJavaScript/TypeScriptを書くエディタとして利用する」を指針にしています。
これはVSCodeであらゆる言語を書くため、多くの拡張機能をインストールし、結果として動作が重くなったことの反省からです。
そのため、JavaScript/TypeScriptに関係しない拡張機能はインストールしないで運用しています。
また例外的に次の拡張機能はインストールしています。
Vim
Vimのキーバインディングがないと生産性が大きく落ちるため
Material Theme
テーマの拡張機能です。VSCodeとVSCode Insidersでテーマを分けると、どちらを使っているか判別しやすくなります。
注意する点
VSCodeではcodeというシェルコマンドが用意されており、引数にディレクトリを渡すことで、指定したディレクトリをルートとしてVSCodeを開いてくれます。
$ code project/
Insidersにもcode-insidersシェルコマンドが用意されています。
利用方法は同じなので同じ感覚で使えます。なので、コマンドの存在を知って使える状態にしておくことが重要です。
$ code-insiders projects/
macOSでシェルコマンドを利用するには、「Cmd + Shift + T」で開くコマンドパレットから「Install ‘code-insiders’ command in PATH」を選択しインストールします。
感想
これらを意識することでVSCodeの調子が悪くなっても緊急避難が可能です。
ただ、根本的な解決には至ってないので解決したいです…情報求む!
2019/10/07 - 「技術書典7」にサークル参加してきた
2019/09/22に池袋で開催された技術書典にサークル参加してきました。今回はJAMStackの既刊を持たず、Slack App開発本を2冊頒布してきました。
だいぶ遅れてしまいましたが、「ブログを書くまでがイベント」ということで、新刊の話、当日の様子や反省を書こうと思います。
今回の新刊
「Slack App開発レシピ」を頒布しました。
これは技書博で頒布した「Slack App開発ガイド」の続編にあたるものです。
「Slack App開発ガイド」では機能の動作や設定方法をあくまで機能ベースな説明を行いました。
「Slack App開発レシピ」はそれと対応するように、作りたいアプリベースでどういった機能を使い、どういったアーキテクチャを用いるのか…といった実践的な説明を行うことを目指しました。
ただ、この命名は完全に失敗で、「どっちが初心者向けですか?」と尋ねられることが多かったので、「開発ガイド 実践編」といった名前にするのがベターだったと思います。プログラマーなら一瞬で分かる命名をするべきです。
事前準備
本の執筆以外に表紙・DLカード・ポスターの制作を行いました。
表紙
表紙は前回に引き続きSlack風の表紙を採用しました。
表紙を見るだけで、何を取り扱っているかわかるので個人的には気に入っています。
自分は絵がかけるわけではなく、グラフィックデザインに成熟しているわけでもないので、こういったアイディアで勝負していくのが適切な戦略だと感じています。
また、ここ最近行われたデザイン変更にも対応しており、メッセージ入力欄のデザインも変更しています。
DLカード・ポスター
今回もDLカード、(お品書き兼)ポスターを作りました。
DLカードは「開発ガイド」のものに合わせて色とタイトルを変更したものにし、ポスターは2冊が等価に見えるようなものにしました。
ブース用品
前回まで半透明のブックカバーを使っていたのですが、今回は表紙を見てもらいたいので透明のものに変えました。色を強めに使っている表紙なので主観ですが「映えた」と思っています。
https://www.amazon.co.jp/gp/product/B00W1EBIE0
前回忘れた「あの布」もちゃんと持っていきました!
チェック数と持ち込み部数
チェック数は初めて300を超えました。Slackの知名度を感じる伸び方でした。
ガイド230部、レシピ150部の380部を持ち込み、合計で250部以上出ました。チェックより少ない感じではありますが、2/3程度配れたので満足しています。
推し祭について
今回は運営事務局が新しい取り組みとして「推し祭」をはじめました。これは要件を満たした宣伝ツイートを行うことで、技術書店公式アカウントがリツイートを行うという企画です。
ただ、推し祭の翌日に入稿したため、出るかわからない新刊を宣伝するのは見送りました。取り組み自体はすごくよかったと思うので、もし参加できる機会があれば参加したいです。
自分の新刊だけでなく、他の人の新刊に目を向ける余裕が欲しいです。
当日の様子
3階サークルの話
サンシャインシティでやる技術書典としては初の階層をまたいだイベントでした。そのため、多くの振り返りポストにも見られるように3階だと辛い回でした。
個人的には搬入と撤収がなかなか厳しく、知り合いのサークル主への挨拶があまりできなかったのが残念です。
サークル受付後、3階への階段がありそこで結構な列ができてしまっており、搬入がギリギリになってしまった。
撤収も普段は閉会30分ぐらい前から始めていたのですが、今回は16時代からイベント終了まで人が来たので撤収開始が本来の時間になってしまいました。
撤収の際、BOOTHやとらのあなへの入庫、宅配便等が2階でしか利用できないために、階をまたいで運ぶのが大変でした。
参加者さんとのコミュニケーション
今まで、GatsbyやNetlifyの本を頒布していて「Gatsbyってなんですか?」、「Netlifyってなんですか?」という質問を結構な回数受けていたのですが、Slackになると知名度があるため、Slack自体は知っている上で活用法や具体例の質問を受けることが多かったです。
幸運(?)なことに3階の奥地という人が少ないエリアだったので、こういった質問も受けやすかったです。
非公式アフター
イベント終了まではなかなか挨拶はできませんでしたが、おやかたさんが主催している「非公式アフター」に参加しました。
アフターに参加しているサークル主さんとは話せました。毎回運営をしてくれて非常にありがたいです。
反省と感想
反省
・開発ガイドと開発レシピではどっちが初心者向けかわからん
→素直に 「開発ガイド 実践編」のようにするべきだった。リーダブルコードを読むべし。
・ポップでも値段と特徴をアピールするべし
→ポスターに値段は書いたけど、立ち読みしてるとわからない
・前日にマイページ入力するのはさすがに遅い
→早く入力して宣伝する
・普段からLTやブログでアウトプットして、執筆に臨む
→考えることを減らしておく。大きな機能を実装する前にリファクタリングしてから実装するよね?
・LTしたら宣伝する
→最後だと忘れるので最初でもいいかも
・とらのあな入庫したやつにDLカード入れるの忘れた
→ごめんなさい
・非公式アフターにDLカードもっていく
→名刺交換感覚で交換したい
感想
しばらく新刊の予定はありません。既刊のアップデートで手を入れられたらいいと思っています。
イベントに関しては「表紙をお願いしたいかも?」という話も頂いてそろそろ執筆以外でお手伝いも考えています。イラストはかけませんがアイディア一発勝負的な表紙を作りたい方はご連絡ください。
2019/09/29 - 技術書典7で『Slack App開発レシピ』を頒布します
技術書典7で『Slack App開発レシピ』という技術同人誌を頒布します。(サークルページ)
この本は、技術書同人誌博覧会で頒布した『Slack App開発ガイド』の続編になります。
開発ガイドではSlack Appの作成方法、利用できる機能の説明・設定方法、機能を使った簡単なサンプルの解説を行いました。
一方、今回頒布する開発レシピでは「ちょっと実践的なアプリ」を例として、どういった流れで実装、どういったコードで実現するかといったポイントを解説しています。
目次
1章 Slack App開発の基礎
2章 構築構築とFunctionsの基礎
3章 定期的に実行されるアプリの作成
4章 外部DBを利用したアプリの作成
付録A タスク自動化ツール『Zapier』の利用
52ページと薄めの本で500円で頒布予定です。
対象読者
『Slack App開発ガイド』を読んだ。または、Slack Appを作ろうとしたことのある人。
Node.jsまたはJavaScriptにある程度、親しみのある人。
Firebaseの入門にネタを探していた人。
Slackが好きで、効率化やコミュニケーションの活性化に興味のある人。
1章に簡単なまとめは用意していますが、前作「Slack App開発ガイド」でそれぞれの機能の特徴や設定方法がわかっている前提です。いつもの本よりはちょっと難しいぐらいの位置づけで書いています。
取り扱うアプリ
開発レシピで取り扱うアプリは2つです。
Channel ranking :Slackの盛り上がっているチャンネルを通知するアプリ
Command tracker: Slack上のSlash Commandで打刻を行うアプリ
2つのアプリともFirebaseのCloud Functionsを利用して実装しており、それに加えてChannel rankingではCloud Schedulerを利用したスケジューリング処理、Command trackerではFirestoreに入力された時刻を保持しています。
2019/09/19 - Node.jsでファイルを直接実行した際にしか動かない処理を書く
Node.jsで他のファイルから呼び出すためのファイルを書いた時に、その関数をいい感じに実行したいと思ったことはないだろうか?具体的にはテストから呼び出すほどでもない用途でnode index.jsを叩いた時だけ動く動作を実現したい。
私は昔からRubyを書いており以下のような記述で、ファイルを直接実行した際にしか動かない処理を書くことができるのを知っていた。
sample.rb
class HogeClass
def some_method
end
end
# `ruby sample.rb`を叩くと実行される。他ファイルからの読み込み時には動作しない。
if $0 == __FILE__
# do someting
end
これをNode.jsに置き換えると次のようなコードで実現できた。便利だ。
index.js
modules.exports = () => {
}
if (require.main === module) {
console.log('`node index.js`のように実行の起点となる時だけ実行される。')
console.log('`require("./index")`のように読み込まれると実行されない。')
}
参考: https://nodejs.org/api/modules.html#modules_accessing_the_main_module
2019/09/08 - フロントエンドNightで『JSXでつくるDSL』というLTをしてきた
gifteeさんのオフィスで開催された『フロントエンド Night #1』というイベントでLT枠を頂き『JSXでつくるDSL』というLTをしてきました。
話したこと
JSXからJSのオブジェクトに変換することでXMLやYAML、プレーンテキストへの変換が容易に行なえます。
また、JSXのシンタックスはエディタでサポートされているので、JSDocによるドキュメンテーション、フォーマッターのサポート、TypeScriptによる型チェックなど多くのメリットを享受できます。
このアイディアを元にLTに落とし込みました。スライドにはありませんが、JSXからPowerPointを生成するデモを行いました。ぎりぎりフロントエンドだと思います。
jsx-review
今回のデモ用にjsx-reviewというJSXをRe:VIEW形式に変換する実用性のないライブラリを書きました。
ただ、コンセプトは伝わる実装だと思うので、興味のある方はぜひ最強のDSLを作ってみてほしいです。
https://github.com/mottox2/jsx-review
感想
LTをする前はすごい不安だったのですが、LTのデモでそれなりに「おー」みたいな声が上がったので安心しました。懇親会はカジュアルな雰囲気で多くの人と話すことができて楽しかったです。ピザがめちゃくちゃ多かったです。
gifteeの皆様、勉強会の運営ありがとうございました。
.@kikunantoka さんからgifteeでギフトをいただきました!これは嬉しい! pic.twitter.com/PkWO6pMylE— もっと@技術書典7 お89C (@mottox2) September 6, 2019
ギフト、嬉しいです。
2019/09/07 - Node.jsでコマンドを実行したい時に使える『execa』の紹介
Node.jsでCLIのコマンドを実行する際、標準モジュールとして用意されている「child_process」を使う。ただ、調べてみたところNext.jsやGatsby.jsといったフレームワークの内部では「execa」というライブラリが使われていた。そこで気になったのでexecaについて調べた。
https://github.com/sindresorhus/execa
execaかはなにか?
child_processメソッドを改良したもの。
改善点として次のような点が挙げられている。
Promiseインタフェースを採用
最終行の改行コードを除去
クロスプラットフォームでshebangバイナリをサポート
Windowsサポートの改善(内部ではcross-spawnが利用されている模様)
ローカルでインストールしているコマンドの優先実行
エラー表現の改善
利用方法
コマンド、引数をそれぞれ引数として渡す。
execaの返り値はChild Process Result。その中の標準出力stdoutを変数に格納し利用できる。(exitCode, stderrといったものも利用できる)
const execa = require('execa');
(async () => {
const {stdout} = await execa('echo', ['hello world']);
console.log(stdout);
//=> 'hello world'
// 同期処理用のメソッド
execaSync('echo', ['hello world']);
})();
引数に分割せず文字列を直接渡して実行するcommandメソッドも用意されている。
const execa = require('execa');
(async () => {
// 引数に分割せず文字列を直接渡して実行する
await execa.command('echo unicorns');
// 同期処理用のメソッド
execa.commandSync('echo unicorns');
})();
自分用のコードを書く際には機能的なメリットはあまり感じられず、真価を発揮するのはクロスプラットフォームで実行されるコードやライブラリを作成する時だろう。ただ、メソッドが少なく覚えやすく罠が少ないという点だけでも採用の価値はあるように思えた。
2019/09/01 - Firestoreの実践的知見を得られる『Firestore Mastery』を読んだ
Firebaseを使ってウェブサービス開発のお手伝いをする機会があった。その際に特に迷ったのが「NoSQLなFirestoreをどう使っていくか?」という点だ。データのモデリングや、データの読み書き権限を定義するセキュリティルール、クライアントとサーバー(Cloud Functions)のどちらでデータの書き込みをするのか等、考えることが非常に多い。
また、Firebaseは盛り上がっているがネット上にある記事には導入部分のものがほとんどで運用を意識したものや踏み込んだ解説のあるものは少ない。1
そこで今回読んだのがコミックマーケットで頒布された『Firestore Mastery』という同人誌だ。
Firebaseの中でも重要で難しいとされるFirestoreに絞って解説がされており、効果的にFirestoreを活用していく方法について書かれている。
対象読者は次のように書かれている。
Firebaseのチュートリアルをクリアし、ステップアップを目指している方
Firestoreの効果的な利用方法を学びたい方
業務レベルでFirestoreの利用を検討されている方(まえがきより)
チュートリアルレベルの内容は省かれており、過去にサーバーサイドでSQLを用いたプロダクト開発、JavaScriptがある程度読めることが前提になっているので、Firestore未経験の方にはマッチしないかもしれない。
ただ、一度でもFirestoreを触って、実務への導入に悩んでいる方にはピッタリの本だと思う。
商業誌にするには難易度が高く「これぞ同人誌!」いった内容だった。
目次
第1章 Firestoreの基礎
1.1 Firestoreを始める前に
1.2 Firestoreのデータモデル
1.3 ドキュメントの操作
1.4 リアルタイムアップデート
1.5 アトミックオペレーション
1.6 Cloud Functionsの利用
第2章 セキュリティルール
2.1 セキュリティルールを書く際のルール
2.2 ユーザ認証
2.3 スキーマ検証
2.4 データのバリデーション
2.5 一括書き込みのセキュリティルール
2.6 セキュリティルールのテスト
第3章 Firestoreのデータモデリング
3.1 ドキュメント設計の原則
3.2 Firestoreでの1:1リレーション
3.3 Firestoreでの1:nリレーション
第4章 Firestoreでユーザを管理する
4.1 ユーザ管理機能概要
4.2 サインアップ
4.3 会員情報を更新する
4.4 ユーザの退会処理
第5章 Firestoreでショッピングサイトを実装してみる
5.1 アプリケーション要件概説
5.2 買い物かご
5.3 商品購入
5.4 レビュー機能
Firestoreの基礎
ドキュメントやコレクション、サブコレクション、リファレンスといった概念を公式ドキュメントよりわかりやすい説明がある。その後は利用ケースごとにサンプルコードが記載されており、どちらとも「Firestoreを始める時に欲しい」と思う内容だった。
Webでのオフライン対応や、Cloud Functionsで作成されるドキュメントを監視する手法など知らないことも多く、Firestoreを使ったことのある人でも一度確認した方がいい内容だと感じた。
セキュリティルール
Firestoreで一番難しいのが、データの読み書き権限やバリデーションを定義するセキュリティルールだと思っている。公式ドキュメントや「Firebaseを使ってみた」系の記事を見ても薄いルールが多く実際にどういう定義をするのかが分からないと感じていた。
だが本章ではセキュリティルールを形作るユーザ認証、スキーマ検証、データバリデーションをそれぞれパターンごとに解説している。ユーザ認証だけでもユーザID、IDトークン、カスタムクレームのパターンについて解説しており、現時点でこれより詳しい日本語文献はないと思うほどの内容だった。
データモデリング
NoSQL、中でもドキュメント志向なFirestoreでのデータモデリングについての章では、基本的な考え方を抑えた上で1:1、1:nといったRDBでいうリレーションの例を出してデータモデリングを説明している。
データのリレーションだけでなく、正規化・非正規化、マップ/リスト・サブコレクションといった「どっちを使えばいいのか分かりづらい」系のトピックにも踏み込んでくれており、手元においておく本として非常に心強い。
ショッピングサイトの実装
実際のサービスを作る際にどういった考え方で実装するのか?という話を「RDBが得意としているECサイト」という題材でまとめてくれている。約20ページに渡って、実際の設計とその理由を説明してくれており非常に参考になる。今までの総まとめ的な内容にもなっていた。
まとめ
Firestoreには日本語のドキュメントも用意されているがここまで踏み込んで書かれた日本語文献は他にないと思う。
Firestoreのチュートリアルを行って、実務に導入するまでには大きな隔たりがあると感じていたが、この本がその溝を埋めてくれると思うので、Firestoreを検討している方は読むとよさそう。
最後にもう一度『Firestore Mastery』のBOOTHリンクをおいておく。
Firestore Mastery - shiodaifuku - BOOTH
感想
BOOTHで見たとき電子版がないため購入を躊躇していたが買ってよかったと思う。結果的に価格以上の価値を感じた。
「Firestoreは簡単なデータ構造のアプリだけなのでは?」と感じていたがそんなことはなく、Firestoreの可能性を感じさせてくれた。
テクニックだけでも「ドキュメント変更の検知を行ってCloud Functionsでのデータを受け取る」・「ChangeLogをサブコレクションで持つ」など目から鱗なトピックがたくさんあった。
今まで書いたコードでも直したい箇所が出てきたので、少しずつ直していこうと思う。
注釈
あるにはあるが断片的で、全体像を掴むのは難しいと感じている。 ↩
2019/08/21 - CLIで利用するNode.jsの書き捨てプログラムを作成するコツ
プログラマーであれば単純作業をプログラムに任せると思います。今回は備忘録を兼ねてNode.jsで書き捨て前提のプログラムを書く際に、よく使っているテクニックをまとめてみました。
やっていることは同じなので他の言語を使っている方でも利用できるものです。
標準入力・出力に対応する
標準入力に対応して、ファイル内を変更しないで使えるようにしておくと便利です。
process.stdin.on('readable', () => {
let chunk
while ((chunk = process.stdin.read()) !== null) {
process.stdout.write(main(chunk))
}
})
process.stdin.on('end', () => {})
クリップボードを利用する
macOSに入っているpbpasteコマンドはクリップボードのデータを出力してくれるので、次のように利用するとクリップボードからプログラムにデータを受け渡せます。
$ pbpaste | node index.js
逆に出力をクリップボードに格納したい場合にはpbcopyコマンドを利用します。
$ node index.js | pbcopy
ファイル名にタイムスタンプをつけて保存する
何らかのファイルを生成する際にはタイムスタンプをつけるとわかりやすいです。
new Date()で現在時刻のインスタンスを生成してNumberにわたすとunixtimeが得られます。
YYYY/MM/DD hh:mm:ss形式を利用したい場合はJS標準のDateではなくmomentやdayjsを利用すると簡単に実現できます。
const fs = require('fs')
const timestamp = Number(new Date()) // unixtimeを生成
const content = 'something'
fs.writeFile(`results/result-${timestamp}.pptx`, content, function() {})
コマンドを叩いて出力結果を確認する
macOSにはopenコマンドがあっていい感じにファイルやディレクトリを開いてくれます。
openを利用して生成したファイルやログファイルを開くと、プログラムの動作を把握しやすくなります。
const fs = require('fs')
const timestamp = Number(new Date()) // unixtimeを生成
const content = 'something'
const execSync = require('child_process').execSync
const fileName = `results/result-${timestamp}.pptx`
fs.writeFile(fileName, content, function() {
execSync(`open ${fileName}`)
})
オプションによって動作を変える
プログラムを実行する際にオプションを渡して、動作を変えられるようにしておくと便利です。
破壊的な操作を行わずログを出力をする--dry-runのようなオプションや、ファイルを開く--openオプションなどを用意することが多いです。
コマンドラインで渡した引数はプログラム中のprocess.argvに配列で渡ってきます。配列の2番目以降を見る処理を書いておくといいでしょう。
上記のファイルを生成する処理を書く際にオプションとして用意しておくことが多いです。
// process.argv => ['/usr/bin/node', '/Users/mottox2/project', '--open']
if (process.argv.includes('--open')) {
// `node index.js --open`のようにopenを指定した場合のみ実行
}
本格的なCLIツールを開発するのであれば、commander、yargsなどのライブラリを利用すると、キレイに記述できます。
2019/08/11 - おしゃれなコード画像を生成するCLIツール『Silicon』
自分はLT資料を作る際に、『Carbon』というおしゃれなコード画像を生成するWebサービスを利用しています。今回はCarbonをインスパイアした『Silicon』というRust製のCLIツールを発見したので紹介します。
こういった画像がCLIで生成できます。
インストール方法
Rustをインストールしている前提で次のコマンドを実行します。
$ cargo install silicon
$ silicon --versionでバージョン情報が出力されればインストールは成功です。
利用方法
Siliconは画像化したいファイルのパスと、outputオプションで出力先のファイルを指定して動かします。
次のコマンドはsiliconの利用例です。
silicon index.js -o main.png
クリップボードのコードから画像を生成できます。
ただし、languageオプションで言語を指定してコードハイライトを有効にする必要があります。
silicon --from-clipboard -l js -o main.png
背景・影色や、ウィンドウコントロール・行番号の非表示、ハイライトのテーマなどのオプションも指定できます。
helpオプションで指定できるオプションを確認できます。
silicon index.js -o test.png --background '#ffffff' --no-window-controls --no-line-number --theme TwoDark
エイリアスの利用
例の通り、Siliconは多くのオプションを指定することになるでしょう。オプションの初期値を記入する設定ファイルの仕組みも用意されていないので、シェルのエイリアスとして設定することで便利に使えます。
例えば次のようなエイリアスを.bashrcなどシェルの設定ファイルに記入しましょう。
ファイルを引数として与えれば、タイムスタンプをファイル名としたpngファイルが~/Downloadフォルダに生成されるコマンドです。非常に乱暴なエイリアスですが、利便性は高めです。
alias code2img="silicon -o ~/Downloads/code2img-$(date '+%y%m%d%H%M%S').png --background '#ffffff' --no-line-number --no-window-controls"
alias code2img="silicon -o ~/Downloads/code2img-(date '+%y%m%d%H%M%S').png --background '#ffffff' --no-line-number --no-window-controls"
利用例
ファイルを指定して画像を生成する
$ code2img package.json
クリップボードから言語を指定して画像を生成する
$ code2img --from-clipboard -l js
感想
コードを画像化する上でオフラインでも画像を生成できるSiliconは素晴らしい選択肢になると思います。
ただし、2019年08月04日現在は背景の透明化を行うことができません。しかし、Issueは既に立っているので対応されるのを期待しましょう。
(2019年8月9日追記)透明な背景色が使えるようになりました。
Add support for transparency by Aloxaf · Pull Request #31 · Aloxaf/silicon
2019/08/04 - 「技術書同人誌博覧会」にサークル参加してきた
2019/07/27に大田区産業プラザPioで開催された技術書同人誌博覧会(通称「技書博」)にサークル参加してきました。
「ブログを書くまでがイベント」ということですので、新刊の話、次回の新刊、当日の様子や反省、Web担当の話を書こうと思います。
今回の新刊
「Slack App開発ガイド」を頒布しました。(BOOTHリンク)
SlackでGitHubやCircleCIといった開発サービスを始めGoogle Calendarやトレロといったビジネスの方も使うサービス連携を行っているのがそれぞれSlack Appと言われるものです。
今回はSlack Appをテーマに必要度が高そうな8割方の機能に触ることのできる本を書きました。
きっかけ
自分は学生時代から、インターン先の会社のチャットツールをChatWorkからSlackへの移行を行ったり、チャット通知を効果的につかいビジネスサイドのワークフローの改善をしてきました。
数年前からはチャットだけで完結する勤怠の仕組みを作ったり、問い合わせ通知が対応済みなのかひと目でわかるメッセージを作ったり、Slackのポテンシャルを引き出すような利用をしていると思っています。
ただ、Slack Appのドキュメントは豊富なのですが、豊富で何を読めばいいかわからず、全編英語で日本語ドキュメントはごく一部しかない状況です。
この本で少しでもSlackでピタゴラスイッチやカラクリ的なものを作る人が増えると嬉しいなと思いキーボードを手に取りました。
幻の新刊
本当は、ノーコードで対応できるSlackのTips集みたいな薄い本も検討したのですが、執筆期間の関係上手をつけられませんでした。
具体的には次のようなテーマを考えていました。
日本語emojiでエンジニア以外もemojiをつける文化をつくる
UserGroupで部署ごとにメンションしたり、全員参加のチャンネルをつくる
複数ワークスペースで通知が気になる場合は非公式クライアントでシャットアウト
地味に役立つTips集でターゲットはSlackを活用したいビジネスの人や情シス系の人でした。
DLカード、ポスター
毎回、楽しく作っているのがDLカードとポスター。今回も張り切って作りました。
本を書くより、関連グッズを生成する方が向いているかもしれません。なれてきたので知り合いのサークルの表紙やDLカードのお手伝いもできそうです。
今回の新刊は一発芸的表紙なので、統一感を出すのが簡単でした。
#技書博 当日に持っていくポスターを作りました。RGBで作っている部分とCYMKで作っている部分が混ざってるけど…@FORTEgp05 さんのaozarafm技書博回を聞きながら作りました pic.twitter.com/ZoGPVnb3CG— もっと@技書博D-4 (@mottox2) July 25, 2019
#技書博 に向けてDLカードのデザインを検討中。展開しやすい表紙デザインでよかった!裏側にあと一歩工夫が欲しい。 pic.twitter.com/5aHFsnfgG6— もっと@技書博D-4 (@mottox2) July 23, 2019
次回の新刊
(気が変わらなければ)技術書典7で「Slack App開発レシピ」を頒布します。
今回頒布した「Slack App開発ガイド」の知識があることを前提に、中規模なSlack Appをいくつか作っていく内容になる予定です。今回の本よりちょっとNode.jsが書けるぐらいの人を想定して書きます。
もちろん「Slack App開発ガイド」の物理本・DL版も頒布します!
「こういったアプリを作りたい」みたいなものがあれば、Twitter DMや参加しているSlackワークスペースで連絡をください。本に載せやすければレシピとして掲載したいと思っています。
当日の様子
朝
緊張しすぎて6:00に起きました。天気が良くてめちゃくちゃ安心しました。
一応安全マージンを大きめにとって「公式応援ホテル」の「ホテル オリエンタルエクスプレス 東京蒲田」で前日入りしていました。朝ごはんが美味しかったです。
会場
今回は疑似壁サークルといった位置の配置でした。
本当の壁サークルとの区切られたパーティションがあり、後ろのスペースが広かったです。おかげでサークルの準備や片づけが楽に行えました。
入場チケット制になってたこともあり、最後の1時間を覗いて常に人がサークルに来てくれました。
技術書展の67%の入場とのことでしたが、立ち読みも気軽に行え、話しかけてくれる方もいたので、深くコミュニケーションが取れたと感じました。その結果、技術書展の5060%程度の頒布部数になりました。
隣の大岡さんのサークル「くるみ割り書房」は14:00には完売しており、拍手が起こったのが印象的でした。自分も完売してみたい。
人が空いたタイミングで自分も会場を回ることができ、「話したい」と思っていたサークル主さんと話せたのは嬉しかったです。
個人的な反省
あの布を忘れて、裸の机のままの運営になった。
あの布はサークル側にポケットがあってお釣りとかを入れることができて便利です。
800円という価格設定はよくない。
実験的な意味も兼ねて800円にしてみましたが、完全に失敗でした。
「1,000円でいいですか?」と申し訳なさそうに言われた時、申し訳ない気持ちになりました。
次回は500円か1,000円のどちらかに寄せようと思いました。
体力が足りなず、後半は立つ体力がなかった
売り子氏に呼び込みを任せすぎた感じはあった。
隣のサークルで頒布されていた「Google Fit本」を手に入れたので健康になる予定です。
Web担当の話
今回、公式Webサイトの方を担当されてもらいました。ただ、サークル主で新刊を書きつつWebアプリを作っていくのは想像以上にしんどく、拙い点も多く残ってしまいました。(絶妙に使いづらい感じでしたね…)
きっかけは3/9の夜にariakiさんからWebサイトを出してくれないか?という要請を受けて対応しました。
話を受けたときには、イベント名、ロゴ、会場、日時が決まっているだけの状態でした。
コミットログからは3/14・15でサイトの大枠は作り上げている様子が見て取れます。最初はGatsbyJS+Netlifyを採用したサイトでした。その後、もろもろの準備ができ4月に公開しています。
その後、Webカタログを作ろうという話になり、当時興味があったけど本番運用には至っていなかった「Firebase」を使っていいならお手伝いしますよという話になり、本格的にWebサイトの担当を行うことになりました。このタイミングでGatsbyJS + NetlifyからNext.js + Firebase(Hosting/Cloud Functions)のスタックにリプレースしています。
途中に何回か改修をいれていく最中や、データの集計フェーズになると「辛い」と思う点もありかなり知見が溜まりました。もうお仕事でFirebaseを使いたいという話が来ても問題なく対応できそうです。
開発の話は入場時に配布された「公式ガイドブック」の方に寄稿していますので、興味のある方は読んでいただけると嬉しいです。
まとめ
すごいよいイベントでした。技術書展に参加する前の同人誌即売会のイメージに近いイベントで、こういったイベントの初回にサークル主、Web担当として関わることができてよかったです。
次回はウェブ担当に専念しようと思っているのでサークル主としては関われないと思います。
ただ、技術書典よりサークル主のハードルが低いので、はじめての同人誌を書きたいと思っているかたは参加を検討してみてはいかがでしょうか?
次は技術書典7に向けて執筆を頑張っていきます!
2019/07/28 - Google Chromeスクショ術
技術同人誌やブログを書く上で外せないのがスクリーンショットを取ることです。
同人誌を5冊書いていく経験の中で慣れてきたので、自分がスクリーンショットを撮る時に使っている方法を紹介します。
Commandからスクリーンショットを撮る
Chrome DevToolsに慣れている方はご存知かもしれませんが、ChromeにはCommandという概念があります。
Cmd + Option + iでDevToolsを開きCmd + Shift + Pを押してください。
すると次のような入力フォームと項目が出現します。
フォームに文字を入力すると、Commandを絞りこむことができEnterで指定したアクションを実行することが出来ます。
ここにある、「Capture area screenshot」、「Capture full size screenshot」、「Capture node screenshot」、「Capture screenshot」を利用してスクリーンショットを撮ることが可能です。
それぞれの挙動は次の通りです。
Capture area screenshot - ウェブページをドラッグしてスクリーンショットの範囲を指定し取得します。
Capture full size screenshot - ウェブページ全体のスクリーンショットを取得します
Capture node screenshot - DevToolsのElementパネルで選択しているNodeのみのスクリーンショットを取得します。
Capture screenshot - ウェブページの現在見えている範囲のスクリーンショットを取得します。
スクリーンショットのサイズを固定する
スクリーンショットを取っていると、同じような画面でも少しずつずれてしまうのが気になります。
そういった場合には同じようなサイズでスクリーンショットを撮る工夫をしましょう。
ウィンドウのサイズを固定する
DevToolsのCommandから「Toggle Device toolbar」を選択すると、スマホで見たような表示になります。
ツールバーの左はしにあるデバイス名をクリックすると、デバイスのメニューが出てくるので「Responsive」をクリックしましょう。
「Responsive」では画像のように画面のサイズを入力できるので、固定したいサイズを入力しましょう。
その状態で「Capture screenshot」を選択すると常に同じサイズのスクリーンショットを撮ることができます。
ノードのサイズを固定する
DevToolsではスタイルを変更することができるので、widthやheightといったプロパティを変更するとサイズが変更されます。
変更した状態で「Capture node screenshot」を選択すると、好みの大きさのスクリーンショットが取得できます。
ブラウザのサイズを固定する(macOS)
AppleScriptを利用してウィンドウサイズを変更することが出来ます。
osascriptを使えばシェルから直接実行することが可能なので、次のコマンドを使ってブラウザ自体のサイズを固定しています。
osascript -e 'tell application "Google Chrome"' -e 'set bounds of front window to {300, 300, 1440, 960}' -e 'end tell'
余計な要素を隠す
「ノードのサイズを固定する」でやったようにスタイル変更で対応します。
要素ごと消したいときは、display: noneやDOMごと削除。
要素の位置を維持しつつ、隠したい時はvisibility: hidden;やopacity: 0;といったスタイルを追加。
要素の主張を減らしたい時は、opacity: 0.5といったスタイルで半透明にします。
目を向けたくない要素にopacity: 0.2を付与した例。どこに注目すべきか一瞬でわかる。
(本の場合、もう少し不透明度をあげないと薄くてわからないはず)
この辺りはCSSの知識になりますが、スクリーンショットの前加工としてCSSが使えるといった発想さえ持っておけば応用は無限にできます。
それでは良いスクショライフを!
参考
Run Commands With The Chrome DevTools Command Menu | Tools for Web Developers | Google Developers
2019/07/21