parcelでビルド結果から別ファイルを出力するプラグインをつくるまでの道のり

Misoca Advent Calendar 2017 - Qiita : 18日目のエントリーです。


以前、RailsでWebpackerをparcelに置き換えるにはどうしたら?という記事をQiitaに書いた。

qiita.com

この中で、しれっと以下のようなことやっている。

  • ビルド結果からfingerprint付きのファイルを出力したい
  • マッピングが定義されたjsonファイルを吐き出したい
  • というプラグインを作った

実際に作ったプラグインはこれ。

github.com

コード自体は大したことないが、作成する際にドキュメントに書かれている方法だけでは厳しく、parcel自体のコードを読むことでそれっぽいものが作れたという経緯があった。なかなか面白かったので完成までの道のりを記事にしてみる。

欲しかったもの

元の記事にも書いてある内容と同じになりますが、簡単に言うと entry.jsというファイルをビルドした場合に、

  • entry-aUjc10lx83jjXwlechKSaxa3Le9kSjfe.js
  • manifest.json

のようなファイルを吐き出し、manifest.jsonには

{
  "entry.js": "entry-aUjc10lx83jjXwlechKSaxa3Le9kSjfe.js"
}

が記録されている、みたいなことをしたい。

プロダクションで利用する際に、ビルド結果に差分があった場合にキャッシュではなく新しいファイルを参照するように、fingerprintが付与されたファイルを配信したいが、都度scriptタグのsrcを書き換えるのはメンテナンスのコストが高く、別途jsonファイルにマッピングを記録し読み替えるようにしたい、といった具合。

つまり、

  • View上 : 何らかのヘルパー経由でentry.jsを指定
  • 何らかのヘルパー : manifest.json経由で実際に読み込むjsファイルを解決
  • ブラウザ : entry-aUjc10lx83jjXwlechKSaxa3Le9kSjfe.js をロード

といった流れになる。

parcel自体の機能で実現できないか?

そのような機能はまだサポートされていないように見えた。

オフィシャルドキュメントのProductionビルドのあたりを見てみると、htmlからjsをロードした状態とし、htmlをビルド対象とすることでjsのファイル名をユニークなものにしてくれる、いった機能はすでに提供されているっぽい。

SPAを構築する場合などではこれで充分そうだけど、今回の目的とは少し違うようだった。残念。

参考: https://parceljs.org/production.html#set-the-public-url-to-serve-on

自力でなんとかする

ポイントとしては、 「ビルド結果が出力された後の時点で実行したい」といった一点かと思う。

parcelのオフィシャルドキュメントを見ていると、3つの拡張方法が存在するようで、以下のように理解した。

  • Asset
    • ファイルに応じてパース、依存解決、transformなどを行い、変換後コードを生成する
  • Packager
    • 出力ファイルタイプに応じて、Assetで変換したものを取り纏めて実際のファイル出力を行う
  • Plugin
    • parcelビルドを非標準的な方法で自由に拡張する場合に利用する

単純に扱えるファイルの種類を増やしたい場合などはAsset/Packagerを利用するのが正しいアプローチのようだが、今回実現したいことにはファイルタイプは関係なく、純粋に出力結果となるファイルのみを考慮したいので、Pluginを利用するのが正しそう。

プラグインを作る

まずはドキュメントに記載されているプラグインの説明を見てみる。 (https://parceljs.org/plugins.html#plugin-api)

Parcel plugins are very simple. They are simply modules that export a single function, which is called by Parcel automatically during initialization. The function receives as input the Bundler object, and can do configuration such as registering asset types and packagers.

Publish this package on npm using the parcel-plugin- prefix, and it will be automatically detected and loaded as described below.

記載されているサンプルコードも抜粋。

module.exports = function (bundler) {
  bundler.addAssetType('ext', require.resolve('./MyAsset'));
  bundler.addPackager('foo', require.resolve('./MyPackager'));
};

上記を見るからに、単一のプラグインをpackage.jsonに追加するだけで、一気に対応するサポートファイルを追加したりすることができるようだ。

これはこれでとても便利そうですが、Asset/Packageは今回は使わないので、違うアプローチを取る必要がありそう。

では、引数で与えられている bundler が一体何者なのかを追ってみる。

Bundler

実際のコードは以下。

https://github.com/parcel-bundler/parcel/blob/master/src/Bundler.js

Bundlerクラス自体は、CLIから実行した際にインスタンス化されており、外部からはbundleメソッドのみがコールされる。

parcelによるビルド処理本体の起点であり、本体といっても良さそう。

ただ、addAssetType/addPackagerといったメソッドは存在するが、他にそれらしいメソッドは存在せず。どうやってビルド終了時に処理を実行させれば良いのだろう?

そこで、ポイントとなるのはクラス定義となる部分。

class Bundler extends EventEmitter {

nodejsを利用している方ならお馴染みの、EventEmitterを継承している。 (https://nodejs.org/api/events.html)

つまり、プラグインが受け取るbundlerは何らかのタイミングでイベントをemitしてくる(かもしれない)ことがわかる。

emitしている箇所

以下の2つが該当する。

  • this.emit('buildEnd'); - code
  • this.emit('bundled', bundle); - code

ビルド終了時に処理をしたいので、buildEndかな?と思ったけど、buildEndは成功・エラーにかかわらずemitされてしまう模様。

引数のbundleを参照することで引数に指定した出力ディレクトリなども動的に解決することが出来るので、bundledを参照するのが正しそう。

最終的に完成したプラグインのコード

というわけで、上記を元に作ったプラグインが以下。それほど大きくないので全部貼ります。

const path = require('path');
const hasha = require('hasha');
const fs = require('fs');

module.exports = function (bundler) {
  const logger = bundler.logger;

  const readManifestJson = (path) => {
    if (!fs.existsSync(path)) {
      logger.status('✨', 'create manifest file');
      return {};
    };

    logger.status('🖊', 'update manifest file');

    try {
      return JSON.parse(fs.readFileSync(path, 'utf8'));
    } catch(e) {
      logger.error('manifest file is invalid');
      throw e; 
    }
  };

  bundler.on('bundled', (bundle) => {
    const dir = path.dirname(bundle.name);

    logger.status('📦', 'PackageManifestPlugin');
    logger.status('📁', `     dir : ${dir}`);

    const f = bundle.name;
    const hash = hasha.fromFileSync(f, { algorithm: 'sha256' });
    const ext = path.extname(f);
    const basename = path.basename(f, ext);
    const hashFile = path.join(dir, `${basename}-${hash}${ext}`);

    logger.status('✓', `  bundle : ${bundle.name}`);
    logger.status('✓', `        => ${hashFile}`);    

    // create hash included bundle file
    fs.createReadStream(f).pipe(fs.createWriteStream(path.resolve(dir, hashFile)));

    const manifestPath = path.resolve(dir, 'parcel-manifest.json');

    logger.status('📄', `manifest : ${manifestPath}`);

    const manifestValue = readManifestJson(manifestPath);
    manifestValue[path.relative(dir, f)] = path.relative(dir, hashFile);

    fs.writeFileSync(manifestPath, JSON.stringify(manifestValue));
  });
};

parcel-plugin-bundle-manifest/BundleManifestPlugin.js at master · mugi-uno/parcel-plugin-bundle-manifest · GitHub

だいたい以下のような流れで処理してる

  • bundler.on('bundled', ... が処理の起点
  • bundle.name で出力されたファイルへのパスを取得する
  • ファイル内容からhashを作成し、fingerprint付きのファイルをコピーする
  • manifest.jsonファイルを作成する。すでに存在する場合はマージする
  • manifest.jsonファイルを書き込む

終わってみれば大した内容ではない。

あとは、名称を parcel-plugin-xxx といった形でnpmに公開すると、parcelビルド時にpackage.jsonのdependenciesを元に自動的にプラグインが実行されるようになる。

最初は parcel-plugin-manifest とかにしようかと思ったけど、私が一等地っぽい名前を取ってしまうのは如何なものかと思ったので、parcel-plugin-bundle-manifestにした。

www.npmjs.com

作ってみて

EventEmitter周りとかは後々追記される可能性もありそうだけど、ドキュメントだけではなく、コードも見るのが大事だよな〜と改めて感じた。

プラグインを作る過程の中で、基本的な動作とかもなんとなく理解できるようになってくるので、とても勉強になってよかった。

manifestファイルの吐き出しについては、もしかすると将来的にparcel自体の機能としてサポートされるようになるかもしれない。自分としてもそちらのほうが安心なので、ぜひ期待したい。

parcelについて

少しズレるけど、parcel自体についての個人的な所感。(個人的なものです)

まるで設定なしで魔法の如く動いているように理解してしまいそうだけど、実際にはwebpackのloaderなりpluginなりがやってくれていたことを裏側で隠蔽して意識しないで良いようにしてくれているだけなので、フロントエンドのビルド周りで理解しないといけないことが格別減るというわけではないと思う。

(知らないまま使っても良さそうだけど、ハマったときに即死しそう。)

でも、ゼロコンフィグで動かそうというのはとても快適に感じたし、cssファイルをエントリーに取ってビルドできる点などは、webpackのExtractTextPluginにつらみを感じていたので「そうそう、これがやりたかったんだよ!!」という気持ちになった。

これからも出来ることは増えていくだろうし、webpackに取って代わる日が来るのも有り得るかもしれない。

とりあえずどうなっても良いように、webpackへのガッツリ依存している部分を少しずつ外しておくことで、いつか幸せになれる日が来ることを信じている。


さて、明日は弊社代表の@toyoshiがラズパイで頑張った話を書いてくれるようです。

前回のエントリが400近いブックマーク数になるほど読まれていたので、今回も注目ですね!!

Nuxt.jsとHerokuでお手軽にSSRを体験する

これは、Misoca Advent Calendar 2017 の6日目のエントリーです。

SSR

フロントエンドを駆使したアプリケーションを構築すると、 どこかのタイミングでSSR(ServerSideRendering)と向きあうことがある。

最近はクローラが優秀なので、SSRを行わないSPAでもいい感じにインデックスしてくれたりするので、そこまで神経質になることもないことが多いですが、ファーストビューの速度などを突き詰めていくと、やっぱり選択肢としては使える状態にしておきたいところ。

実際にやろうとすると簡単なものではなく、Railsの場合はreact_railsのようなgemに頼ったりすることになったり、頼っても大変だったりするのが現実だと思う。

Next.js & Nuxt.js

といったわけで、Next.js/Nuxt.jsの名前をちらほら見かけるようになったと思う。

オフィシャルのガイドなどをざっと見て「ふむふむ」程度で終わっていたけど、触りだけでも一度試してみることにした。

個人的に、以前はReactがメインだったが、最近ではVueを使うことのほうが多いので、今回はNuxt.jsのほうをやってみることにする。

Nuxt.js

https://ja.nuxtjs.org/guide

Nuxt.js とはユニバーサルな Vue.js アプリケーションを構築するためのフレームワークです。

だそうです。

本気でVueでのSSR可能なSPAを組もうと思うと、以下のような要素が出てくる。

  • Vue
  • vue-router
  • vue-server-renderer
  • vuex
  • babel
  • webpack
  • 場合によってはexpressなど

その上で、アプリケーション自体の構成からルーティングルールを検討した上で、サーバサイド、フロントエンドどちらのレンダリングでも耐えうる形で作っていく必要があり、普通につらい。

Nuxt.jsを使うことで、ざっくりこのあたりを隠蔽してくれるので、とりあえずの出だしとして細かいことを考えずにコードを書き始めることができる。

Nuxt.jsの敷いたレール上に乗るぶんには楽できるけど、カスタマイズしようと思うと細かい知識が必要になるよ、みたいな話なので、考え方としてはRailsWayとかに近いのかなって印象。

やってみよう!

ゴール

  • Heroku上でNuxt.jsで作ったアプリケーションのSSRを確認できる

やらないこと

  • 凝ったカスタマイズは一切しない

インストールする

スターターテンプレートというものが用意されているので、そちらを利用する。

https://ja.nuxtjs.org/guide/installation

$ npm install -g vue-cli 
$ vue init nuxt-community/starter-template nuxt-trial

# 色々聞かれるけどデフォルトで良いのでEnter連打

$ cd nuxt-trial
$ yarn install

試しに動かしてみる。

$ npm run dev

http://localhost:3000/ にアクセスすると、以下のようなページが表示される。

f:id:mugi1:20171203001108p:plain

なんか動いてるようだ。

ちなみにnuxtのコードを見てみると、サーバ自体はconnectを利用してるっぽかった。

このままHerokuに放り込んでみる

インストールされたものはとりあえずあとで見るとして、このままHerokuに放り込んで動くかやってみよう。

FAQにずばりそのままのページが用意されている。

https://ja.nuxtjs.org/faq/heroku-deployment

心を無にして上から叩く。 (herokuのcliはインストールしてあるものとする)

$ heroku create
$ heroku config:set NPM_CONFIG_PRODUCTION=false
$ heroku config:set HOST=0.0.0.0
$ heroku config:set NODE_ENV=production

package.jsonに追記して、Heroku側でよしなにビルドしてくれるようにscriptsを足す。

  ~
  "scripts": {
    ...
    "heroku-postbuild": "npm run build"
  },
  ~

デプロイする

git push heroku master

これでブラウザからHerokuのアプリケーションを見てみると、ローカルと同様に動いていることが確認できる。

簡単。

SSRをやってみよう

では、肝心のSSRがちゃんと動くかを確認してみる。

確認のために以下のようなページを作ってみる。

  • 2ページあって行き来できる
  • ページごとに初期化時に何らかのAPIのデータを取得して表示する

API自体はなんでもいいので、THE COLOR APIというサイトから適当にカラー情報を取得することにする。

http://www.thecolorapi.com/

コンポーネントをつくる

非同期データのためにaxiosを追加しておく。

yarn add axios

色情報を取得するAPIとカラースキーマを取得するAPIの2つがあるので、その2つをページにしてみる。 内容は、ランダムなカラーをもとにデータを表示する超簡易的なもの。

pages/color.vue

<template>
  <section class="container">
    <div>
      <span>color</span>
      <span>|</span>
      <span><nuxt-link to="/scheme">scheme</nuxt-link></span>
    </div>

    <div><img :src="data.image.named" /></div>
  </section>
</template>

<script>
import axios from 'axios'

export default {
  async asyncData () {
    const hex = Math.floor(Math.random() * 16777215).toString(16)
    const { data } = await axios.get(`http://www.thecolorapi.com/id?hex=${hex}`)
    return { data }
  }
}
</script>

pages/schema.vue

<template>
  <section class="container">
    <div>
      <span><nuxt-link to="/color">color</nuxt-link></span>
      <span>|</span>
      <span>scheme</span>
    </div>

    <div><img :src="data.image.named" /></div>
  </section>
</template>

<script>
import axios from 'axios'

export default {
  async asyncData () {
    const hex = Math.floor(Math.random() * 16777215).toString(16)
    const { data } = await axios.get(`http://www.thecolorapi.com/scheme?hex=${hex}`)
    return { data }
  }
}
</script>

この内容でコミットし、改めてHerokuにpushする。

動きを確認してみる

/color

f:id:mugi1:20171203001140p:plain

/scheme

f:id:mugi1:20171203001455p:plain

ちゃんと動いてるっぽい。

(ちなみに画面上で遷移しようとすると、クライアント上でhttpsからhttpのXHRとなるので、Mixed Contentのエラーで落ちる。対処するのが面倒なので、Chromeの場合はURLバー横のアイコンから強制的に許可して回避する。)

Chrome DevToolsのNetworkタブを使って、画面上のリンクで遷移した場合のリクエストを見てみても、初回表示以外はxhrリクエストになっていることがわかる。

f:id:mugi1:20171203001635p:plain

肝心のSSRはということで、ダイレクトアクセスした直後にページのソースコードを見てみる。

f:id:mugi1:20171203002004p:plain

API経由で取得する画像へのURLがファーストビューとなるHTMLに含まれていることが確認できる。

というわけで

これだけであれば、たいした苦労もなく、SSR可能なVue.jsアプリケーションをHerokuで動かすことができた。

使い込んでいくと細かいカスタマイズなどで苦労することはありそうだけど、この簡単さは強力だな〜という印象。

もう少しちゃんとしたアプリケーションを作って検証してみてもいいかなという気持ちになった。

明日は @oosawatechによる「野生化」の話です。

野生化...!?

「プロを目指す人のためのRuby入門」が躊躇なくオススメできる完成度だった

前々から色々とお世話になっている西脇.rbの伊藤淳一さん(@jnchito)が、Rubyの入門書を出版されることになり、ちょうど私が読者のターゲットに近い存在ということで1冊見本誌を頂きました。

というわけで、書評というと生意気ですが、写経も交えつつ読了したので、感想を書いてみます。

ちなみに私自身は

  • プログラマとしては9年くらいやってる
  • Ruby歴自体は2年くらい
  • 業務で使うようになったのはここ1年くらい

といった具合。

実践感の強さ

まず、3章(=かなり序盤)の段階で「例題解くときはテスト自動化をしような」という説明が出てきたときにこれを感じた。

写経できるような入門書はいくつか見てきましたが、初っ端から「テストは自動化して効率よくやっていこうな」というスタンスの本はなかなか無いのでは。

個人的な経験では、通常入門書を写経していくと、「とりあえずコードを書く→動す→なんか落ちる→コードとにらめっこする」みたいなことになることが多かった覚えがある。(そしてイヤになる)

本書の場合、まずはテストを書いてエラーにしてから、実際のコードを書いてテストが通るという流れを踏んでいくので、1つずつ着実に理解していける感がある。

(さらにRubyの入門しながら、しれっとTDDの基礎的な部分も触れられるのでお得感がある)

現実を教えてくれる

読み進めていくと、

  • 実際にはこれは使わないことが多い
  • 幾つか書き方があるけど、こっちが主流
  • こういうのが不具合の原因になりやすい

みたいな、言語仕様・文法だけを学んだだけでは把握できない部分に言及している箇所がかなり多いことに気付く。

実際このあたりは業務で使うときにかなり重要で、学ぶタイミングが少なかったり、単純にググるのが難しい概念だったりもする。

そういったところで都度道筋を教えてくれるのは初心者には嬉しいように感じた。

また、英語で出てくるバックトレースなどについて「英語が苦手な人も辞書を片手に頑張ってね」という記述があるのもなかなか新鮮だった。 わりと入門書では「今は理解しなくていいですが〜」みたいなことを書いてあったり、そもそも触れられないみたいなことも多いですが、ぶっちゃけ理解しなくていいわけがないので、そのあたりの現実突きつけてくれるのは大事。

実際のところ私自身も英語は苦手なので「うっ、すいません..!」って感じだった。

プログラミング初心者向けではなく、Ruby初心者向け

書籍内の冒頭でも触れられていますが、プログラミング自体が初心者という人にはハードルが高めかもしれない。基本的な概念の説明は無いので、「変数...?」みたいな状態だと厳しい。

逆に言うとそのぐらいちゃんとターゲットを絞った本なので、合致した層が手に取ると、かなり参考になる内容が多いと思う。

Rubyを使っていて、「自分はもうRubyバリバリ使えるぜイェーイ!」って言える人以外は、とりあえず買って目を通してみるといいかもしれない。私自身も、もう完全な初心者ではないかな〜と勝手に思っていたけど、普通に知らないことがボロボロ出てきたので、いい感じに振り返れてとても良かった。

写経しやすい

全体を通して、そもそも写経を想定して作られてるなって感じがした。

基本的には各章に1つ練習問題があるので、ざっくりとした理解チェックをするには最低限それをやればいいし、ガッツリ学びたければ、都度記載されてるサンプルコードを全て写経していくこともできる。

ちなみに紙質も違うらしく、開いたときに維持しやすいらしい。

実際維持しやすかった。すごい。

とりあえず理解度が全然違うので、写経しながら読むことをオススメする。

適宜必要な前提知識を教えてくれる

人によっては正規表現の章で、「正規表現知らないならそっち勉強してから戻ってきてね!」と、一度書籍の外に追い出されるという体験をすることになる。

このあたりは「プロを目指す人のための」という名前がピッタリだなという印象だった。実際のところ、根本の部分がフワフワしてると理解できないので、そのあたりをいい加減にしたままRubyでの正規表現の使い方を教えられても困るわけで、「知らないなら知ってから戻ってきてね!」というスタンスはとても潔いし、そうだよな、って感じがした。

トータルでの感想

私の個人的な感情とかは無視しても、かなりの良書だと思った。

Qiita等での伊藤さんの記事で普段お世話になっている人も多いと思うけど、あのわかりやすさがそのまま本になったような感覚。

周りにRubyに精通した人がいて質問できる環境なら良いが、そうじゃない場合には学ぶのが難しい要素というのが実際それなりにあって、本書の内容である程度カバーしてくれるのがとてもいいと思う。

2年前のRuby勉強し始めたころにこの本があれば〜〜〜!!と何度も思った。SIerからRuby使うようなWeb系への転職を考えている人とかには最適の1冊になるのでは。

ターゲットを絞っているぶん、合致するとかなり刺さる内容が多いのかもしれない。

  • 「これからRuby勉強したいんですけど〜」
  • 「それなりに書けるようになったけど、いまひとつ自信ないわ〜」

みたいな人がいたとすれば、今後はこの本をオススメすることになると思う。(私は後者だったので刺さった)

さいごに

見本誌で頂いたという立場を考えると、サクラのような書評になってしまっているように見えるかもしれないけど、内容をじっくり読んだ上で良い内容だと判断したので、躊躇なく書かせて頂きました。

これはもう、「プロを目指す人のためのRails入門」の出版が待ち遠しいですね!

RSpec/Capybaraのテストコードを画面操作から出力するChrome拡張をつくった

ほぼ表題の通りの内容で、Chrome拡張を作ってみた。

完成度としてはまだまだだけど、とりあえずざっくり触れる程度にはなったので公開した。

f:id:mugi1:20171001221735g:plain

github.com

chrome.google.com

イコン画像は、カピバラの写真を適当になぞって作った。

なんでこんなものを?

Capybaraのテストコードを書くのが面倒だなって感じることが多かったのが1つの理由。

TDD的に、先にテストコードを書いていけるのが理想だな〜とは思うものの、Webアプリケーションの開発をしていると、現実には一度は画面から一通り確認して、その後にfeature specを書く流れが多いように感じる。

そしてCapybaraでfeature specを書こうと思うと、

  • 「これはテキストじゃなくてIDで選択しないとダメか〜」
  • 「あ〜、これはfindしてからsetしないといけないのか〜」

という感じで、スムーズに書けない自分がいる。

そのあたりを都度試行錯誤しているのが面倒だな〜と思い始めて、「どうせ最初に一通り画面を触ってるんだから、そのときの操作がそのままfeature specとして出力できればいいじゃん!」と思って作り始めた。

あとは、Chrome拡張って興味があったけどなにげに作ったことがなかったので、やってみたかったというのもある。

つかったもの

ContentScript ⇔ Background ⇔ DevTools という流れでデータのやり取りを非同期で行う必要があった。

ごちゃごちゃしそうだったので、非同期になる箇所はすべてeventsでラップして、全データがDevTools上にVue&Vuexで構築たストアに集約するようにしたところ、わりとスッキリした。

役割としては、

  • ContentScript : 操作の監視 & 情報を集約してeventsをpublish
  • Background : ContentScriptとDevTools間を中継するのみ
  • DevTools : ContentScriptのデータをsubscribeしCapybaraのコードを生成

みたいな感じになった。

できること

  • テキストフォーム・テキストエリアの入力 → fill_in の生成
  • ラジオボタンの選択 → choose の生成
  • チェックボックスの選択 → check/uncheck の生成
  • セレクトボックスの選択 → select の生成
  • 要素クリック → find(xxx).click / click_link / click_button の生成

あたりはできている。

一番やりたかった部分として、何でその要素を特定できるかで生成コードが変わるようになってる。

fill_in '一意のラベル', with: '入力値' # ラベルで特定できる
fill_in 'id', with: '入力値' # idで特定できる
find('.class').set('入力値') # classで特定できる
find(:xpath, '/div[1]/input[1]').set('入力値') # 上記全てが無理な場合はxpath

できないこと

まだまだ発展途上感がある。 現時点で以下は対応できていない。

  • 画面遷移後の継続動作
  • visit とかも作る
  • fill_in 前の要素の click が不要なので省く
  • などなど..

というわけで

公開してあるので、興味のある方はどうぞ。

個人的には、label/id/class/xpathの自動判別が作れたのである程度満足しているけど、機能的にもっと充実させていきたい。

要望などがあればissueにもらえると嬉しいです。

RailsDevelopersMeetupでWebpackerの話をした

2017.8.24に行われたRailsDevelopersMeetupにて、機会を頂いたので10分枠でLTをさせていただいた。

rails-developers-meetup.connpass.com

突然のメッセージ

ここ数日はコードも書かずにスプラトゥーンをやる日々だったけど、ある日Twitter経由で、主催の@yoshi_hiranoさんから「地域.rb発のLTを実現できないかと思い、Toyama.rb主催ということでリモートでLTをお願いできないか」という主旨のメッセージをいただいた。

「えっ、自分!?」と思い、宛先を間違ってるんじゃないかと何度もメッセージを見返したけど、やっぱり自分だった。

第1〜3回目の登壇者には著名な方も多く、参加者の期待に応えられる話がちゃんとできるかな〜?と心配だったけど、「せっかくの機会なのでやってみよう!」ということで、発表させてもらうことにした。

なお

自分は10分のLT枠だったけど、Keynote枠のうちのお一人が伊藤さん(@jnchitoさん)だったのにはかなり驚いた。

Toyama.rbを作ったそもそものきっかけは伊藤さんと言っても過言ではないので、まさかそれが同じイベントでリモート発表する日が来るとは予想もしてなかったし、とても嬉しかった。

事前練習

妻にお願いして、少しだけ練習した。

「何もわからなかったし、聞いてる途中ちょっと寝てたわ」という感想だった。

まあそうですよね

話した内容

ぶっちゃけた話、業務でのRails歴がまだ浅いので、人前で話せるレベルのスキルも知識も持っていない。

ただ、唯一Webpackerにはがっつり関わった経験があり、良いこともツラいこともそれなりに味わったので、今回のテーマにした。

というわけで資料です。

speakerdeck.com

10分間

10分と時間が決まっていたので、最終的にかなり内容を削った。

本当はもう少し具体的に移行手順的な話もしたかったんだけど、「結局どう感じたのか?」「よかったの?どうだったの?」といった、自分の感想的な部分を強めに出してみた。

おそらくフロントエンドにはそこまで深く関わってない方も多く参加されてただろうと予想しているので、結果的には踏み込みすぎないで丁度いい具合の仕上がりになったかな〜と勝手に思っている。(本当か?)

リモート発表

今回は、普段お仕事をしている富山の自宅からリモートでの発表だった。

初めての体験で、聞いている方の顔や雰囲気が感じ取れないのが少しさみしい感じはあったものの、意外となんとかなるもんだな、と思った。

Hangoutは負荷が高いと色々トラブルが起きやすいイメージがあったけども、そんなこともなく、基本的にはスムーズだった。

手応え的に

Twitterで感想とかを見ていると、わりとWebpackerの話聞きたかったという方も多かったようで、完全な空振りとかではなかったようで安心した。

そしてすでに使ってるという方には、ツラかったポイントは響いたようだった。そうだよね。わかるわかる。

ちなみに

音が聞き取りやすいけどマイクが良いのか部屋が静かなのか、といった感想をみかけた。

部屋は普通なのでマイクを紹介しておくと、Yetiをつかっております。

Blue Micro Yeti USB 2.0マイク 15374

かなりでかい。
また、このマイクのおかげで、たまに「YouTuberだ!」という扱いを受けている。

やってみて

今までは北陸界隈や社内での発表ばかりで、ある意味安全な範囲で活動をしていたけども、今回始めて外に飛び出しての発表だった。(正確には家の中だけど)

正直かなり緊張していたけど、自分なりにちゃんとやれたと思うし、自信もつけられた。

あと、これは毎回思うけど、発表するとそのために知識や資料を精査する必要があるので、どちらかというと自分が学ぶことがかなり多くてとても良い。

今後も積極的にやっていきたい。

あらためて

当日聞いていただいた皆様、ありがとうございました!
主催者の皆様、おつかれさまでした!

このような機会を頂けたことに感謝しています。ありがとうございました!

フロントエンド勉強会をやった

Toyama.rb 第20回目のイベントとして、フロントエンドの入門的な勉強会をやった。

toyamarb.connpass.com

以前から懇親会などで「もくもく会以外でどういうことやりたいです?」と参加者に聞いていたところ、フロントエンドがよくわからん!という意見が多かったので、テーマに据えて勉強会をやってみることにした。

お盆

わりと面白いテーマだったので人数も結構集まるかな〜ワクワク、って思っていたら、お盆ど真ん中に設定してしまったので、普通に少人数だった。

完全に私のミス感はあるけど、人数が少ないぶん、ゆるい雰囲気でできたのでこれはこれでよかったかなって思った。(思いたい)

babel & webpack 入門

1つは私自身が話をさせてもらった。

自分自身まだまだ解ってないことが多いな〜と日々感じることが多いけど、良く使う構成であればさくっと構築できるようになってきたので、頑張ってまとめてみた。

gitpitch.com

何を話そうかな〜?と悩んだけど、自分が最初に触れたときに一番混乱したのが、babelとビルドツール(webpack/browserify/gulpなど)を同時に利用した場合の設定まわりだったので、そこを中心に話した。

資料作成&話をしてみて

「こんなもん解るわけないよな」って改めて思った。

登場人物というか、必要なツール群が多く、かつブラウザの話なのかnode.jsの話なのかとかでも混乱するし、なかなかつらい世界だった。

自分は全部一気に学ぼうとしてパニックになった記憶があるので、資料にも書いたけど、1つずつ覚えていく、というのも大事なのかもしれない。

GitPitch

発表用の資料作成にGitPitchを利用させてもらった。

github.com

  • Markdownで書けるのはやっぱりすごいいい。短時間で作れた。
  • デフォルトでデザインがいい感じになるのがありがたい。
  • コードのハイライトとかがめっちゃ便利だった。
  • デフォルトでcsstext-transform: uppercase が適用されてるので、デフォルトだと見出しが全部大文字になっちゃう。
  • → カスタムcssで打ち消せるけど、これはデフォルト無効でいいのではって思った。

感想としてはすごいよかった。 また利用させてもらうと思う。

フロントエンド開発の足回りとしてのyarn(あるいはnpm)

@hikaruworld さんの発表。 今までの歴史的経緯と、yarn/npmの話だった。

歴史の話がおもしろかった。知らないことも多かった。

話を聞きながら、いつの間にやらみんなyarn使ってるな〜って思ってた。

そして「今の話なので、来年はまたどうなってるかわかりません」という言葉を聞いて、ウッってなっていた。つらい世界や…

モブプロで学ぶReact/webpack/babel

話を聞くだけじゃつまらんかな〜というので、実際のコードを対象にどんな感じで環境を作ってコードを書いていくのかを、モブプロ形式でやってみた。

内容

Toyama.rbのHPで、次回のイベントと最近のイベントをconnpassから動的に取得して表示している。

  • 変更前 : jQueryとlodash#templareでゴリゴリに実装
  • ゴール : React/ES6で書き換える

進行

当初はドライバーを交代しながらやっていこうかな〜と思っていたんだけど、普通にツラいし時間も全然足りないだろうな、という判断から、私がドライバーをやりながら終始ツッコミをもらうというスタイルにした。

モブプロというかコーディング実況的な感じになったけど、スムーズに進んだのであれで良かったかなって思ってる。

結果

1時間半程度だったけど、以下を達成できた。

  • webpackによるReact/ES6のビルド環境の構築
  • Reactによるコードの書き換え
  • コンポーネントの分割
  • 公開

当日作成したPRはこちらです。(コミットコメントがなんちゃってイングリッシュなのは突っ込まないで..)

環境の構築もそうだけど、ビルドがコケたときにどうするか?とかを見ながら話できたのは良かったなって思った。

途中、デフォルト引数の部分でビルドエラーが起きて、原因としては babel-preset-envの設定を書き忘れていた。そのときは .babelrcに env を足してサッと動くようにしたけど、「なんでそのエラーからそれが原因だって解ったんですか?」という声があがって、「あ、うん、そうですよね…」という気持ちになった。

感想

わりといい内容だったんじゃないのかな?と主催者は勝手に思っている。

見てた感じ、モブプロは結構ウケが良かった。またやりたい。



ちなみに、実際にはLTもあった。けど、オフレコ的な話もあったのでここには書かないでおく。

AgileJapan2017 富山サテライトで発表してきた

2017/6/24に開催されたAgileJapan2017 富山サテライト会場にて機会を頂いたので、発表させていただきました。

資料はこちらです

speakerdeck.com

内容

Misocaでのミーティングやふりかえり方法について、やり方やメリット、注意点などについて話しました。

SIerから転職してからまだ数ヶ月ということもあって、以前感じていたジレンマなども踏まえて話すことができたので、ITベンチャーなどが少ない富山県のエンジニアに対しては響く内容になったのでは?と勝手に思っています。

意識したところ

現実的な話をしたかった

過去の経験として、こういった発表や資料を見た際に、

「すごい!勉強になる!あ、でもうちじゃ無理だわ!!」

と思うことがありました。

前提となっている環境の部分のハードルが高すぎて、とっても参考になるしタメになるけど、導入ができないな〜というものです。 組織が根本から異なるので、やっぱり難しいんですよね。

という経験も踏まえ、少しでも現実的な着地点をお伝えできるように意識しました。

具体的には

  • 「人間ってそういうものです」
  • 「そうはいっても無理だよね〜」

  • 「じゃあ、それを踏まえてどうするか?」

みたいな話を交えました。

方法より理解、そして小さくやっていく

上記スライドではあまり触れていませんが、実際の発表時には「とにかくコンテキストや意識を共有するのが大事だよ!」というのを何度も繰り返し話していました。

手法だけを導入しても上手くいかないのは、意識の部分での共有が不足しているために反発が生まれるせいだと思っていて、同時にその意識を共有するという部分が一番難しい点だとも思います。

歴史が長かったり規模が大きい組織では、現実的には無理だろうという部分もあるので、そのあたりも踏まえて、小さくやっていこうね!というお話をさせて頂きました。


資料を作る過程で、自分でも「なるほど!こういうことだったのか!」という発見もいくつかあり、とても楽しかったです。

(がっつり資料をレビューしてくれた社内の皆さんには感謝です)

当日参加して聞いていただいた皆様、ありがとうございました。

さー!次は何しよう!