eyecatch
Mon, Dec 21, 2015

ReactをAtomパッケージ開発に使ってみた

私は今HPEのFort Collinsオフィスに居候している。 HPEは最近、Reactを使ったUXフレームワークであるGrommetを開発していて、私が扱っている製品もそれを使う兆しが見えてきた。 Grommetはいずれ仕事で触ることになりそうなので、まずはReactの勉強をと思い、とあるAtomパッケージの開発に敢えて使ってみた。 このエントリには、その作業の中で得た知識などについて書いた。 ただし、Reactを使った開発のノウハウみたいなものまでは得ていないので書いていない。 (因みにGrommetはGitHubで公開されているが、ほとんど話題になっておらずスターも現時点で245しかついていない。。。) Reactとは ReactはFacebookが開発しているWeb UIのフレームワークで、MVCのVだけを実装したもの。 2013年に最初のバージョンが公開され、世界中で流行ってきているらしい。 その特徴(というかほぼ全容)は仮想DOM(Virtual DOM)。 ReactのAPIを使うと、リアルDOMと一対一で対応する仮想DOMのツリーを作ることができ、UIを組み立てられる。 リアルDOMの構築や更新はReactが最適化された方法でやってくれるので、性能がいいUIができるらしい。 因みに、仮想DOM自体はReact特有の技術ではなく、別の実装もある。 もう一つの特徴はJSX。 これは、JavaScriptのコードの中で、XMLみたいな構文で仮想DOMを記述するための拡張構文。 これを使うとReactコードが見やすく簡単に書けるけど、当然普通のJavaScript実行環境では動かないので、プリコンパイルなどが必要になる。 FacebookはReactを使った開発にFluxというアーキテクチャの採用を推奨している。 FluxはMVCアーキテクチャに置き換わるもので、従来の複雑なデータフローに反発し、一方向のシンプルなデータフローを提供する。 Fluxは単なるアーキテクチャで、その全体の実装を支援するフレームワークは現時点では無い。 (多分。Relayが一部支援してくれるっぽい。) Reactを触った感想 Reactは本当にちょっとしか触っていないので、あまりよく分かっていないんだろうけど、なんだか使いにくかった。 Reactは仮想DOMを作るところしか助けてくれないので、他のことは全部自分でやらないといけない。 FacebookはReact用のウィジェットすら提供していない。 昔仕事で全部入りのDojoを使っていたので、それとのギャップをすごい感じた。 そのうえ、他のフレームワークやライブラリと組み合わせて使おうとすると仮想DOMが壁になってくる。普通のフレームワークはリアルDOMを扱うからだ。 例えば、JavaScriptを書いているとすぐjQueryを使いたくなるが、これでリアルDOMを直接いじってしまってはReactを使う意味がない気がする。 AtomパッケージでReactを使う Reactはnpmでも提供されていて、Atomパッケージの開発に簡単に使える。 パッケージのpackage.jsonのdependenciesにreactとreact-domを入れておけば、パッケージコード中で以下の様に仮想DOMを作れるようになる。 var React = require('react'); var ReactDOM = require('react-dom'); class MyComponent extends React.Component { render() { return <div>Hello World</div>; } } ReactDOM.render(<MyComponent />, node); BabelによるJSXの手動コンパイル JSXのコンパイルにはBabelを使うのがいい。 手動コンパイルにはBabelのコマンドラインツールが必要で、これはnpmで提供されている。 npmコマンドはAtomに同梱されているので別途インストールは不要。 以下が手順の詳細。 Babelのコマンドラインツールのインストール 任意の場所で、 npm install -g babel-cli を実行すると、Babelのコマンドラインツールがグローバルにインストールされ、任意の場所でbabelコマンドが使えるようになる。 Babelの定義ファイル作成 適当なフォルダ(プロジェクトのルートなど)に.babelrcというBabelの定義ファイルを作り、以下を書いておく。 { "presets": ["react"] } Reactプラグインのインストール .babelrcに書いたpresetsの値は、コンパイルにReactプラグインを使うという意味。 なので、以下のコマンドでReactプラグインを(ローカルに)インストールする必要がある。 cd <.babelrcを置いたフォルダ> npm install babel-preset-react コンパイル babelコマンドでコンパイルを実行する。例えば以下を実行すると、 cd <.babelrcを置いたフォルダ> babel src -d lib src/*.jsxがコンパイルされて、lib/*.jsに出力される。 language-babelパッケージによるJSXの自動コンパイル 上記Babelによるコンパイルは、Atomならlanguage-babelパッケージで自動化できる。 以下、Atomパッケージの開発でlanguage-babelを利用する手順を書く。 language-babelのインストール language-babelをAtomのSettingsなどからインストールして、language-babelのSettingsで、Allow Local Overrideにチェックを付ける。 Babelの定義ファイル作成 手動のと同じ内容の.babelrcをパッケージプロジェクトのルートに置く。 package.json編集 パッケージプロジェクトのpackage.jsonのdependenciesの下あたりに以下の定義を追加して、BabelとReactプラグインへの依存を張る。 "devDependencies": { "babel-core": "^6.1.2", "babel-preset-react": "^6.1.2" } 上記定義を追加したら、apm installを実行して追加した依存をダウンロードする。 因みに、devDependenciesはdependenciesと似てるけど、開発時だけに必要なモジュールを定義するプロパティ。 devDependenciesに書いたものはapm installしたときはダウンロードされるけど、パブリッシュされたものをインストールするときにはダウンロードされない。 language-babelの設定ファイル作成 language-babelの設定は.languagebabelというファイルにかく。 これに以下の様な内容を書いてパッケージプロジェクトのルートに置く。 { "babelMapsPath": "lib", "babelMapsAddUrl": false, "babelSourcePath": "src", "babelTranspilePath": "lib", "createMap": false, "createTargetDirectories": true, "createTranspiledCode": true, "disableWhenNoBabelrcFileInPath": false, "suppressSourcePathMessages": true, "suppressTranspileOnSaveMessages": false, "transpileOnSave": true } これで、<パッケージプロジェクトのルート>/src/*.jsxが、Atomで編集して保存したときにコンパイルされ、<パッケージプロジェクトのルート>/lib/*.jsに出力されるようになった。 BabelでJSXをコンパイルする場合の制限 手動にしろ自動にしろ、JSXのコンパイルにBabelを使う場合、BabelがCoffeeScriptに対応していないので、CoffeeScript + JSXでは書けない。 JavaScript + JSXで書かないといけない。 Minified exception React周りでバグを作りこんでエラーが発生した場合、コンソールに以下のようなエラーメッセージが出ることがある。 Uncaught Error: Minified exception occured; use the non-minified dev environment for the full error message and additional helpful warnings.
eyecatch
Sat, Dec 19, 2015

impress.jsでのプレゼン資料作成をサポートするAtomパッケージ - impress

Atomのパッケージを作った話。 ついでに、パッケージプロジェクト内で別のプロジェクトを取り込んで使いたい場合に、Gitのサブモジュールを使ってはダメという話。 impress.js impress.jsというJavaScriptライブラリがある。 HTML5とCSS3とJavaScriptでプレゼン資料を作るためのライブラリで、これを使うと、PowerPointやKeynoteといった従来のツールによるものからは一線を画す斬新な資料を作ることができる。 公式のデモを見ればその魅力を堪能できる。 デモを見ると分かるが、Preziに触発されたライブラリだ。 Preziでも非常に新鮮な資料を作れるが、ほぼ有料で、また作成した資料をPreziのサーバに置かなければいけないので、仕事で使う資料作りには使いにくい。 その点impress.jsは、MIT(とGPLv2)で公開されていて自由に無料で使えるのがよい。 ただし、Preziがスライドという概念から大きく脱却しているのに対して、実のところimpress.jsで作れる資料はあくまでスライドベースだ。 従来のものに比べてスライドの並びに制約がなく、スライド間の遷移がダイナミックというだけだ。 impress.jsでもまあ工夫すればPreziのような資料は作れるが。 独自のオーサリングツール/ビューワに依存するPreziに対し、impress.jsは標準的なHTML/CSS/JavaScriptにだけ依存しているので、jQueryなどのWeb技術を活用してスライドを作れるという副次的なメリットはある。 impress.jsは、2012年に最初のバージョンが公開されてからもう4年近く経つが、未だにそれほど広く使われている様子はない。 PowerPointが幅を利かせているせいもあるだろうが、その使い辛さから利用をためらう人が多いのではないだろうか。 impress.jsはあまりドキュメントが充実しているとは言えない。 GitHubに公開されているREADMEには、使い方はソースを見よ、それで分からないなら使うなとある。 さらにソース中には、impress.jsを使うには、HTMLとCSSのスキルに加えてデザイナーのセンスも必要とある。 かなりハードルを上げている。 このハードルをクリアしていたとしても、実際、impress.jsで資料を作るのはPowerPointに比べて10倍は大変だ。 impress.jsはスライド(impress.js用語ではステップ)間の遷移を制御してくれるだけで、各スライドのコンテンツを作るという部分に関してはなんのサポートも提供しない。 テンプレートもなければ、表やグラフを書く機能もなく、アニメーションも作れない。 そういうことをしたければ、自分で別途ライブラリを探して使うなりしないといけない。 ちょっとした図を書くにも、テキストエディタでちまちまHTMLとCSSを書いて、ブラウザで表示して確認して、思った通りになっていなければディベロッパツールでデバッグして、Web UIでも書いていたんだっけという気になってくる。 impressパッケージ そんな負担を少しでも軽くしたいと思って作ったのがimpressパッケージ。 同じ目的のツール(i.e. オーサリングツール)は実は既にいくつかあった。 なかでも、Hovercraft!というのが高機能で便利そう。 ただ、これらはPowerPointほど自在にスライドを作れるまでには至っておらず、結局は仕上げにHTML/CSSを手でいじる作業が必要になる。(と思う。) また、jQueryのプラグイン使ってかっこいいことしたいとか言う場合にも、手でコードを書かなければいけない。 つまりテキストエディタを開かなければいけない。よってAtomを起動することになる。(私は。) であれば、オーサリングツールもAtomに統合されていた方が便利なんじゃないの? というのがimpressパッケージを作った動機。 まだ機能は少なくて、新規資料プロジェクトの雛形生成、 ステップをリスト表示するビュー表示、 プレビューができるだけ。 ゆくゆくは、GUIでステップの配置や角度を編集する機能、GUIでステップ内の図を作成する機能を作りたい。 あとできればアニメーションを付ける機能とかも。 Hovercraft!みたいにHTML書かなくてもいいよ、というのを目指すつもりはなくて、あくまでもコーダーのための、コーディングを補助するツールを目指す。 パッケージのサブモジュール impressパッケージは、新規資料プロジェクトの雛形生成機能などのため、impress.jsプロジェクト(のフォーク)をサブモジュールとしてとりこんでいる。 最初はGitのサブモジュールコマンド(git submodule)を使って取り込んでいて、上手くいっているように見えたが、パブリッシュ後に次のような問題が発生した。 即ち、試しにimpressパッケージをインストールしてみたら、サブモジュールのフォルダの中身がからっぽだった。 これは、AtomのパッケージマネージャがパッケージをGitHub Releasesからダウンロードしてインストールするからだ。サブモジュールの中身はGitHub Releasesに登録されるアーカイブに含まれない。このGitHub Releasesの挙動は、サブモジュールを含むGitプロジェクトをクローンした場合、デフォルトではサブモジュールはクローンされないというGitサブモジュールの仕様に関係しているのかもしれない。 この問題をきっかけにGitサブモジュールについてちょっと調べてみた。 蝙蝠本によると、Git開発チームはあまりサブモジュールコマンドの開発に熱心ではなく真面目に作らなかったらしい。 また、あるブログによればサブモジュールコマンドは大分まえからオワコンらしい。このブログによれば、今は多くの場合git subtreeを使うのがいいとのこと。git subtreeは蝙蝠本にもPro Gitにも載ってないのだが。 git subtreeでプロジェクトを取り込んだ場合、親プロジェクトのクローン時にサブプロジェクトもデフォルトでクローンされる仕様だ。 (というか正しくは、サブモジュールと違って、子プロジェクトが親プロジェクトにマージされているから、一緒にクローンされるというだけ。) これを使ってimpressパッケージを構成しなおしてみたら件の問題が解決した。 因みにやりかたは、impressパッケージプロジェクトのルートにimpress.jsというフォルダを作った後、以下のコマンドを実行しただけ。 git subtree add --prefix impress.js [email protected]:kaitoy/impress.js.git master --squash ということで、Atomのパッケージに別のプロジェクトを取り込んで使いたい場合は、git
eyecatch
Wed, Dec 2, 2015

Atomパッケージをアンパブリッシュする

Atomのパッケージをリリースすることをパブシッシュというが、リリースを取り消すことをアンパブリッシュという。 この記事はそのアンパブリッシュのやり方などについて。 筆者の環境は以下。 Windows 7 x64 Atom 1.2.4 Git for Windows 2.6.3 アンパブリッシュのやり方 リリースしたパッケージのプロジェクトのルートフォルダ(package.jsonがあるところ)にcdして、apm unpublishを実行するだけ。 または、任意のフォルダでapm unpublish <パッケージ名>を実行する。 特定のバージョンだけアンパブリッシュしたい場合は、apm unpublish <パッケージ名>@<バージョン>。例えばapm unpublish [email protected] 注意すべき点 1: Git Bashでアンパブリッシュするとエラー Git for WindowsのGit Bash上で、Windows版Atomに付属するapmでapm unpublishを実行すると以下のエラーが出る。 Error: EINVAL, invalid argument at new Socket (net.js:157:18) at process.stdin (node.js:693:19) at Unpublish.module.exports.Unpublish.promptForConfirmation (C:\Users\Kaito\AppData\Local\atom\app-1.2.4\resources\app\apm\lib \unpublish.js:87:48) at Unpublish.module.exports.Unpublish.run (C:\Users\Kaito\AppData\Local\atom\app-1.2.4\resources\app\apm\lib\unpublish.js:126:21) at Object.module.exports.run (C:\Users\Kaito\AppData\Local\atom\app-1.2.4\resources\app\apm\lib\apm-cli.js:226:32) at Object.<anonymous> (C:\Users\Kaito\AppData\Local\atom\app-1.2.4\resources\app\apm\lib\cli.js:6:7) at Object.<anonymous> (C:\Users\Kaito\AppData\Local\atom\app-1.2.4\resources\app\apm\lib\cli.js:17:4) at Module._compile (module.js:456:26) at Object.Module._extensions..js (module.js:474:10) at Module.load (module.js:356:32) コマンドプロンプトでやるべし。 注意すべき点