「Middleman で作った web サイトを Travis + GitHub pages でお手軽に運用する」でのセキュリティ上の不具合がありましたのお知らせ

以前書いていたブログ記事で、致命的なセキュリティ上の不具合があったのでその訂正についてお知らせします。

どのような不具合かというと、本ブログ記事にしたがって middleman の自動ビルドを Travis に設定している場合、GitHub トークンが Travis のログに残ってしまい第三者に悪用されるという可能性があるというものでした。
該当の箇所はすでに修正してありますので、今後の設定については問題ありません。

今まで参照してくださっていたみなさま、大変申し訳ありませんでした。
今利用中の Token については expire していただいて、新しい Token を再設定していただけるとありがたいです。

不具合について連絡してくださった @azu_re さん、対応方法を連絡してくださった @hokaccha さん、大変ありがとうございましたっ!!

Sapporo.js - 2013.07.27に参加しました / Angular.js/Knockout.js についての感想など

Sapporo.js - 2013.07.27 に参加してきました。

今回は、 @tmaeda さんが Angular.js@iakio さんが Knockout.js について発表をしてくださいました。

簡単にですが、お二方の発表についてのぼくの感想をまとめておきます。(主に自分のメモ用)

AngularJSのご紹介

  • "Angular.js はフレームワークではない! HTML の再実装だッ!(バーン"

    • なるほど!という印象。今までは、HTML に独自拡張の属性をつけるのがあまり好きになれなかったんですが、こういう方針なら頷けます。
  • JSON の serialize/deserialize やコミットのタイミングなど、外部 API とのやり取りは特にサポートしていないのでプログラマが自分でなんとかする必要があるとのこと。

    • (Ember Data は自前でなんとかしようとしているんですが、今一歩力及ばずな印象。そもそもこのあたりはフレームワークで解決できない、ドメインに特化した領域ななんですねぇ...)
  • 変数名で DI を実現しているとことで、minify とは相性が悪そう -> 書き方で回避できるよ!

    • ちょっとしんどいですよねぇ... minifier のオプション(あるのかな..?)とかで設定できるとよいんでしょうか?

Getting start with knockout.js

  • 生の JavaScript の延長線上に存在している気がして、メソッド名を見るだけでもなんとかくどうなるかわかりやすい

  • "Knockout.jsはフレームワークではなくライブラ リだ(ズギャーン"

    • なるほど、こういう Knockout.js はこういう位置づけなんですね
  • ko.computed は依存性をプログラマが明示する必要がない、っていうのはかなりすばらしいと思いました。 -> "定義時に一回実行してみる"

    • こういう割り切りは大好きです。(Ember.js だと、自分で明示する必要があるので若干面倒です。そこまで人間が管理するの?っていうのはちょっとストレスフル。)
  • あまり大それたことをやっているライブラリではないので、Backbone.js を触ったことがあるひとならすぐに馴染めるのかな、という感じでした。ぼくは Knockout.js は触ったことがないですが。

その他

ちなみに、この MV* の空気を読まずぼくは Ruby の Middleman について発表してきました。

発表資料はこちら:

当日いただいた感想:

今回、ぼくからの発表お願いを快く引き受けてくださったお二人には感謝の気持ちでいっぱいです。

今後共よろしくお願いいたします。

Ember.js を Middleman から簡単に使うために ember-middleman を作りました

今巷で人気の Ember.js を Middleman で簡単に使うために ember-middleman という gem を作りました。

どんなことができるか、簡単にご紹介します。

gem によるライブラリの管理

Ember.js とそれが依存する Handlebars を gem で管理できるようになります。

# Gemfile

gem 'ember-source', '1.0.0.rc5'

これで、Asset pipeline のパスに Ember.js と Handlebars が追加されます。

//= require handlebars
//= require ember

Ember.js の頻繁なアップデートに対応するのが楽になります。

handlebars サポート

source/javascripts/templates 以下に handlebars でファイルを作成することができるようになります。

例えば、source/javascripts/templates/ok_button.js.handlebars というファイル名で以下の内容を保存したとします。

<div>
  <button {{action someAction}}>OK</button>
</div>

すると、JavaScript の中からは、 Ember.TEMPLATES['ok_button'] という名前でコンパイル済のテンプレートにアクセスできます。

Ember の view に対しても、 templateName: 'ok_button' という設定を行うことが可能になります。

これで、テンプレートファイルを html の中に埋め込まなくてよくなるのでメンテナンスしやすくなります。

ジェネレータ

Ember.js で使うであろうファイル/ディレクトリ群を自動生成することができます。

準備のために、以下の Gemfile を用意します:

# Gemfile
source 'https://rubygems.org'

gem 'middleman'
gem 'ember-middleman'

この状態で、以下のコマンドを入力します:

$ bundle exec middleman init . --template=ember

これでテンプレートが自動生成されます。

プロジェクト作成の際の手間が減ります。

使い方

使い方はいたってシンプルです。 middleman 用の Gemfile と confing.rb に以下の一行を追加するだけです:

# Gemfile
gem 'ember-middleman'
# config.rb
activate :ember

最後に

以上、ember-middleman のご紹介でした。

具体的に ember-middleman を利用しているプロジェクトはこちらにあるので、使い方に迷った方はご参照くださいませ。

Ember.js + Middleman の組み合わせで開発をしたいと思った方は選択肢のひとつに加えていただけると幸いです:D

Middleman で作った web サイトを Travis + GitHub pages でお手軽に運用する

先日 Middleman を使って sapporojs.org をリニューアルしました。 その際に得られた Middleman での web サイト運用の知見をご紹介します。

Middleman って??

簡単に説明すると、静的 web サイトジェネレータです。 Jekyll をご存知の方であれば、似たようなものをイメージしていただけるとよさそうです。 Middleman の方が優れている点は、 Asset PipelineTemplate Helpers などの便利な機能を利用をすることができることです。

逆に Jekyll の方が有利な点としては、 GitHub pages が使えるためデプロイが楽であるという点があります。

そこで今回は、 Jekyll と同じく Middleman を GitHub pages に簡単にデプロイする方法をご紹介します。

流れ

Middleman のディレクトリ構成はおおまかには以下のようになっています:

.
├── build (生成された html)
└── source (人間が編集するファイル)

Middleman で生成した web サイトを GitHub pages で公開するためには、build ディレクトリを root ディレクトリとして gh-pages ブランチに push する必要があります。

そのため以下のような手順を設定し、デプロイを自動化することにします:

  1. Travis でビルドする
  2. Travis で commit を作成する
  3. Travis から GitHub pages に push する

準備

まずは Middleman プロジェクトの用意しましょう。

お使いのプロジェクトがあればそれを、なければ middleman init したものを利用します。

またデプロイ環境には、GitHub pages を利用するため、GitHub にリポジトリを作成しておきます。 source の管理は master ブランチ、デプロイ用に gh-pages ブランチを利用することとしてご説明します。

1. Travis でビルドする

まずは、Travis の設定をおこないます。 詳しくは本家サイトを参照してください。

手元で .travis.yml を作成します。

---
language: ruby
script: bundle exec middleman build

これで、GitHub に push した際に Travis でビルドが実行されるようになりました。

2. Travis で commit を作成する

Travis だと Git に user.name, user.email の設定がされていないため、そのままだと commit が作れません。 そこで commit を作るために必要な環境変数を設定します。

.travis.yml に以下を追記します。

env:
  global:
    - GIT_COMMITTER_NAME=<名前>
    - GIT_COMMITTER_EMAIL=<Eメール>
    - GIT_AUTHOR_NAME=<名前>
    - GIT_AUTHOR_EMAIL=<Eメール>

(名前、Eメールは適宜設定してください)

では、gh-pages ブランチを clone してきて、 ビルドが成功したあとで commit を重ねるよう設定を行いましょう。

.travis.yml に以下の内容を追記します。

before_script:
  - git clone --quiet <リポジトリのURL> build
  - pushd build
  - git checkout -b gh-pages
  - popd

after_success:
  - cd build
  - git add -A
  - git commit -m 'Update'

(この時、リポジトリURL には ssh プロトコルを利用しないようにしてください。接続先の fingerprint の確認を求められて先に進むことができなくなります)

これで、Travis で git の commit を作成することができるようになりました。

3. Travis から GitHub pages に push する

Travis から GitHub に push するためには一工夫必要です。 というのは、GitHub の認証を Travis から通過する必要があるからです。

このためには、以下で議論されているように、https プロトコルで GitHub の OAuth トークンを利用する というのがシンプルな方法です。

では、GitHub のトークンを取得しましょう。(すでに利用可能なトークンをお持ちであればこの手順はスキップしてください) 以下を参考に、トークンを取得してください:

この時、 scope に repo が必要なので忘れず設定してください。

上記で取得したトークンを Travis に設定しましょう。 この時、.travis.yml に書けば GitHub にはアクセス可能になりますが、public な場所に置くと誰でもトークンの権限を利用可能になってしまうので推奨されません。

そこで、TravisAPI を利用して安全に設定することにします。

(初回は Travis へのログインを求められます)

$ gem install travis
$ travis encrypt -r <リポジトリ名> "GH_TOKEN=<GitHub トークン>"

secure XXX という値が返ってくるので、それをそのまま .travis.yml の global -> env に追記します。

env:
  global:
    - secure: <Travis のセキュアキー>

このトークンを利用して GitHub に push する設定を .travis.yml に追記します。

 after_success:
   - cd build
   - git add -A
   - git commit -m 'Update'
+  - '[ "$TRAVIS_BRANCH" == "master" ] && [ $GH_TOKEN ] && git push --quiet https://$GH_TOKEN@github.com/<リポジトリ名>.git gh-pages 2> /dev/null'

git push する際のオプションに気をつけてください。 ここで --quiet の設定を忘れると、Travis のログに GitHub のトークンが表示されてしまいます。

以上で Travis から GitHub に push する設定は完了です。

これで、 master に push するだけで、Travis 経由で GitHub pages に自動でデプロイされるようになりました。 べんり!!

参考

また、手元からも gh-pages に push したくなるという場合もあるかと思います。 そんな時は Rakefile に処理を切り出すというのはいかがでしょうか?

参考までに、ぼくが利用しているものをご紹介しておきます:

最後に

以上で Middleman で作った web サイトを Travis + GitHub pages でお手軽に運用する方法の紹介は終わりです。

今回ご紹介した方法が、みなさまの Middleman を利用した web サイト運用の一助になれれば幸いです:-)

(2013.08.27 追記) 今まで、本記事の通りに設定を行なうと、Travis のログに GitHub のトークンが残ってしまうという不具合がありました。 現在は手順を修正してあるので、本記事に従って Travis の自動ビルドを設定を行った方は GitHub のトークンを expire していただけるとありがたいです。

連絡をくださった @azu_re さん、ありがとうございます!

クライアントサイド JavaScript のパフォーマンス改善には backburner.js が便利!

DOM 処理や Ajax など、JavaScript が外の世界とやり取りする部分というのは、一般的に待ち時間を多く必要とします。

パフォーマンスを改善しようと思った時に、ロジック部分でコツコツと節約するより、まずコストが高い処理を行わないようにするということで、驚くほどの効果を経験をされたことはありませんか?

今までパフォーマンス測定をされた方であればピンとくる部分があることと思います。

そんな時に役に立つのが、今回ご紹介する backburner.js です。

backburner.js って?

backburner.js とは Ember.js の run loop モジュールから切りだされたとても小さなライブラリで、短時間に集中的に発生するメソッド呼び出しの回数を制限したい場合などに利用することができます。

backburner.js ってどう使うの?

例えば、JavaScript で特定のイベントハンドラ内で Ajax 通信を行う場合を考えてみましょう。

$('.action-area').on('mousemove', function(event) {
    // マウス位置を Ajax で送信
});

この例だと、.action-area 要素の上でマウスが動く度にマウス位置を Ajax で送信することになります。WebSocket でやり取りをしている場合でも無い限り、ここまで頻繁に通信を行うことはサーバにとって余分なコストとなる場合があります。

そこで backburner.js です。 上の例を以下のように書きなおしてみましょう。

var backburner = new Backburner(['send']);

function sendMousePoint() {
    var event = this;
    // マウス位置を Ajax で送信...
};

var wait = 100;

$('.handle-area').on('mousemove', function(event) {
   backburner.debounce(event, sendMousePoint, wait);
});

backburner.debounce を使うことで、引数で指定されたメソッドは、同一の Function であれば一定の時間間隔(wait = 100 ms)の中で 1回しか実行されません。 とてもエコロジーですね。

また、いわゆる MVC フレームワークにおいて、モデルの変更をビューがバインドしていて、かつモデルに頻繁に更新が発生するといった場合についても応用出来ます。

これについては、 backburner.js の README に素晴らしくわかりやすいサンプルコードがあるので、こちらを見てみましょう。

モデルのプロパティをひとつひとつ変更していく、というのはよくありえるシチュエーションだと思います。

上述の例のように backburner.js を使うことで、チラツキやもっさり感の原因になりえる DOM の頻繁な更新を抑制することができます。

参考資料

もっと知りたくなった方は、作者の ebryn さんの発表動画とその資料をみてみると良いかもしれません。

それでは、みなさまも backburner.js のすばらしさをご体感くださいませ!

Ember.js をターミナルから触ってみる

最近 Ember.js にはまっています。 せっかくなので、ブラウザを使わずにターミナルからも ember を触れるようにしてみました。

使い方は簡単です。 まずはインストール。

$ npm install -g term-ember

そして実行します。

$ term-ember

あとは ember に触りたい放題です。

term ember> Ember.VERSION
'1.0.0-rc.3'
term ember> var App = Ember.Application.create();
...

ちなみに、各種ライブラリのバージョンを指定して起動することもできます。

$ term-ember --ember 1.0.0-rc2 --jquery 2.0.0

ちょっとしたメソッドの動作確認などに使うと便利かもしれません。

JavaScript 道場を開催しつつ参加してきました

しっかりコードを書きながら他の人のやり方や考え方を共有することができるイベントに参加したいなぁという思いが高まってきていたので、JavaScript 道場というイベントを開催しつつ参加してきました。

JavaScript 道場って?

JavaScript 道場 - connpass の概要がとてもよくまとまっています。

JavaScript 道場は、JavaScript での実践的なコードについて議論をしながらグループでコードを書くイベントです。
普段 JavaScript を書いていて、なかなか上手にできない部分や、汚くなってしまいがちな部分について、みんなで解決方法を模索します。

JavaScript 道場では、JavaScript のプロフェッショナルを師範としてお呼びして、
彼らにアドバイスをもらいながらコードを書くことで、彼らの持っているノウハウを知ることができる機会をご用意いたします。
ぜひ、みなさまが普段から困っている部分を直接質問してみましょう。

Node.js 側の師範として @badatmath 氏を、ブラウザ側での師範として @hokaccha 氏をお迎えします。

JavaScript 道場は、セッションやハンズオンなどのイベントとは違って、考えながらコードを書くイベントです。
目の前のコードに挑むための工夫を、ぜひみなさんのプロジェクトにも持ち帰ってください。

「JavaScript をもっとキレイに書きたい」、「整理されたコードについてもっと考えたい」そんな悩みを抱えている方はぜひお越しください。

あえてひとことでまとめると、チームでコードを書いてお題に取り組むイベントです。(ざっくり)

開催の理由

「ありがたい話を聞く」系のイベントだと、自分で東京に行けばいろいろな種類のイベントに参加することができるし、自分にはあえて札幌で開催する理由はありません。

もちろん、そういうイベントに参加するのはそれで楽しいんですが、現場との距離感というか「明日から自分の仕事につながるもの」をちゃんと持ち帰れるようなイベントに参加したいなぁという気持ちがずっと自分にはありました。

ただ、今までチームでコードを書くイベントはあまり聞いたことがなかったので、せっかく開催するなら自分が参加したいイベントにしたい、という思いで開催を決意しました。 (ちなみに、今回の JavaScript 道場開催にあたって一番影響を受けたイベントは TDDBC in 札幌 です。)

また、このイベントを通じてぼくが実現したかったことは、「自分の身近で JavaScript についてもっと喋れる場ができること」です。 (こう思ったきっかけは、東京のカンファレンスに行くと、ほかの参加者の方々とわりとコアな話で盛り上がれるので、自分が住んでいる札幌でももっとカジュアルに話ができるといいなぁと思ったことでした。)

そのためには、実際にチームでコードに触れて一緒に考えるという経験が一番必要なのではないかと考えたのです。

内容について

午前の部では、 JavaScript を現場で使われている師範をお呼びして、JavaScript を使った開発の話を聞きました。
そのときの講演資料はこちらです:

そして午後の部では、チームでお題に取り組みました。

お題って?

お題といっても、だいぶざっくりした「お客さんの要望」のような抽象的なものだけを用意して、それに対してどうやってアプローチしていくかは完全にチームに委ねるという形にしました。

そして今回のお題はこちらでした:

このうち、どちらのお題に挑戦するかをチームで決めて、好きな方のお題に取り組んでもらいました。

ここでの時間配分は以下の通りです:

時間 内容
13:30 - 13:40 お題発表
13:40 - 17:30 お題
17:30 - 17:50 チームでの感想戦
17:50 - 19:20 チームごとの成果発表

ただ、決まったコードを書くだけではなく、仕様を決めて実装して、そして最後には自分たちの開発を振り返ることができるよう設計したつもりです。 (つまり、ふつうの開発の短縮版にできるよう意識しました。)

各チームでの成果物へのリンクをこちらにまとめています:

最後に

運営者としても参加者としてもとても楽しかったので、ちゃんと開催できてよかったと思っています。 (もちろん、上手くできなかったところやもっと上手くできそうなところはいっぱいあるので、ちゃんと振り返って次につなげます)

師範としてご協力いただいた @bad_at_math, @hokaccha, 一緒に運営してくれた @volpe_hd28v, @puprl, @hachiilcane, そして、参加してくれた方々に深く感謝します。

そして、「次回」というのはすぐには難しいですが、何らかの形でこれからにつながることを考えていきたいですなぁ。

参照リンク