Atomコードリーディング Part 1
目的
GUIアプリのアーキテクチャを学ぶ
最近、SPAやらネイティブアプリやらで、GUIアプリの作成力が求められてる気がする。なので、Atomを教材にしてGUIアプリケーションのアーキテクチャを勉強したいと思った。Atomの実装はいいものと仮定して進めてくけど、まあ大丈夫だと思ってる。昔だったらEclipse、NetBeansが勉強になったのかな、とか考えてたけど、自分には辛そう。
あと、アプリケーションのソースコードだけじゃなくて、ビルドとか開発フローとかも見ておけば参考になるんじゃないかと考え中。大規模アプリだとこの辺りも重要ということで。
エッジな技術の使われ方をみる
AtomがReactやらShadow DOMやらを使ってるというのは有名だと思うけど、そういったものがどこでどう使われるのかをちゃんと見ておきたい。Atomでxx使い始めたよ~、と聞いたらすぐに追えるようにしておきたい。Atomならフロントエンドで面白そうなことはだいたい実践してきそうな感じはある。あと、使われてるライブラリとかもその都度調べたい。
自分が使ってるエディタの中身を知る
自分で使ってるエディタの中身を理解して、あわよくば自分で改造してみたい。普段WebStormを使っていたんだけど、最近のフロントエンドの流れについていくにはエディタを自分でいじるしかない、と感じたのも動機のひとつ。ライセンス料払ってるのに常にEAP版使っているのは、ちょっともどかしい。
そんな感じで端からゆっくり読んでいく。見てるソースのバージョンどんどんあがっていくと思う。とりあえずコードリーディング開始時のコミットをメモ。Atomのバージョンでいうとv0.188.0くらい。
ビルド
アプリのソースをみるだけなら、エントリーポイントから見ていけばいいんだけど、ビルド周りも見ておきたいので、ざっくり流れを追っておく。
ビルド方法
ドキュメントに載ってる。とりあえずスクリプト実行すれば、Applications以下にAtom.appができる。
git clone https://github.com/atom/atom.git cd atom script/build # Creates application at /Applications/Atom.app
script/build
簡単なjsスクリプト。script/bootstrap
を実行して、gruntのbuild
タスクを実行している。
script/bootstrap
はざっと見たところnpmやapmの依存パッケージをインストールしている。
Gruntfileとしてbuild/Gruntfile.coffee
を指定している。gruntもgulpみたいにCoffeeScriptをサポートしていたんですね。
Grunt
build/Gruntfile.coffee
自体にはconfig系を定義してるくらいで、個々のタスクはbuild/tasks/*-task.coffee
などにある。もうgrunt使ってないけど、タスクの分け方は結構参考になる。
build
タスクはその名の通りbuild/tasks/build-task.coffee
にある。build
タスク自体はcompile
、generate-license:save
、generate-module-cache
、compile-packages-slug
タスクに依存してる(macならcopy-info-plist
タスクにも依存)。
compile
タスク自体はGruntfile.coffee
にある。
grunt.registerTask('compile', ['coffee', 'prebuild-less', 'cson', 'peg'])
coffee
タスクだけ確認しておく。
coffeeConfig = glob_to_multiple: expand: true src: [ 'src/**/*.coffee' 'exports/**/*.coffee' 'static/**/*.coffee' ] dest: appDir ext: '.js'
appDir
はmacだと/Applications/Atom.app/Contents/Resources/app/
になる。それ以下に出力されたjsファイルが置かれる。
他にもたくさんgruntタスクがあるけど、必要になったら見る。
起動
atomコマンドのシェルスクリプト見たけど、よくわからなかった。まあ、起動はatom-shellがやってくれるはず。
ドキュメント見てたら、atom-shellのチュートリアルにメインプロセスについて書かれていた。
package.json
のmain
スクリプトを実行するプロセスがメインプロセス(main process)と呼ばれるみたい。main
には./src/browser/main.js
が指定されてるので、これがエントリーポイントだと考えてよさそう。
メインプロセスから実行されるスクリプトはウェブページを生成することによりGUIを表示できる。
atom-shellはウェブページを表示するのにChromiumを使っていて、ウェブページそれぞれにもプロセスがある。それはレンダラプロセス(renderer process)と呼ばれる。
2つのプロセスの詳細な違いは必要になったら調べる。
src/browser/main.coffee
エントリーポイント。start
関数が定義されていて、それが実行される。
start
関数でやってること
CoffeeScriptのキャッシュは特に追ってない。coffee-cashというものを使っていた。キャッシュディレクトリを指定して登録しておけばファイル単位でキャッシュしてくれるみたい。なんか便利そう。
コマンドライン引数のパースはsubstack氏のoptimistというライブラリでやってた。便利そうなので、コマンド作るときに使ってみたい。開発時に使えそうなコマンドオプションにdevモードがある。コマンドオプションの使い方がわからなかったら、この辺り読めばすぐわかりそう。
appモジュールというのはatom-shellアプリケーションのライフサイクルをコントロールするやつみたい。ライフサイクル系のイベントの発火もしてくれる。ここではready
イベントはハンドラを設定してる。ready
はその名の通りatom-shellの初期化が終わったところで発火する。
ready
ハンドラではsrc/browser/atom-application
をrequireして、それのopen
メソッドを呼んでる。いよいよ始まりといった感じがする。
app.on 'ready', -> # ~ 省略 ~ if args.devMode AtomApplication = require path.join(args.resourcePath, 'src', 'browser', 'atom-application') else AtomApplication = require './atom-application' AtomApplication.open(args) console.log("App load time: #{Date.now() - global.shellStartTime}ms") unless args.test
最初に頑張っても続かないので、続きはあとで
参考