Facebookが公開した新しいJavaScriptパッケージマネージャ: Yarn
元記事:
素敵やーん。
日本時間で12日、ちょうど日付が変わったくらいにFacebookが前述の記事を公開した。内容は「JavaScriptコミュニティで圧倒的に力を持っているnpmの代替となる新しいパッケージマネージャ、Yarnを作ったぜ!」というもの。代替といってもYarnはnpmクライアントを完全に置き換えるものではなくて、上位互換を持ったものらしい。
npmに対して、Facebookはかなり前から依存パッケージのインストールにかかる時間を問題視していたみたいだ。これは僕や周囲のエンジニアの反応とも一致するし極めて妥当な感じがする。今回のYarn開発に関するモチベーションはそれだけではなく、同社のJavaScriptコードベースがエンジニアの数と共に肥大化していったことも述べていて、開発にグーグルが協力していることからも大規模サービスにおいてコード管理がいかに負担になっているかを物語っていると思う。
npmの遅さにはFBのエンジニアも辟易していたのね
— ぬこすけ (@pg_nukosuke) 2016年10月11日
アーキテクチャ
Yarnは3つのステップで依存パッケージのインストールを行う。グローバルキャッシュを用意してそこにパッケージを保存しておくのが従来のnpmクライアントとの違い。
Fetching:
次に、ダウンロードすべきパッケージがすでにグローバルキャッシュに存在しているかを確認し、もしなければtarballをグローバルキャッシュに保存する。これによってこのパッケージはオフラインでも利用可能になり、再びダウンロードする必要がなくなる。Linking:
最後にYarnは必要なファイルをグローバルキャッシュからnode_modules
ディレクトリにコピーする。
なるほど、という感じだ。
インストール
npmでインストールできる。
$ npm install -g yarn
使い方
次のようにnpmのサブコマンドに対応するらしい。個人的には、ここはあえて変えずにそのまま置き換えられるようにして欲しかった。
npm install
→yarn
npm install --save <name>
→yarn add <name>
速度比較
適当に選んだ自作nodeプロジェクトの依存項目のみ抜粋したものがこちら。
{ "dependencies": { "es6-promise": "^4.0.5", "isomorphic-fetch": "^2.2.1", "qs": "^6.2.1" }, "devDependencies": { "babel-preset-es2015": "^6.16.0", "chai": "^3.5.0", "karma": "^1.3.0", "karma-babel-preprocessor": "^6.0.1", "karma-chai": "^0.1.0", "karma-mocha": "^1.2.0", "karma-mocha-reporter": "^2.2.0", "karma-phantomjs-launcher": "^1.0.2", "karma-sinon-chai": "^1.2.4", "karma-webpack": "^1.8.0", "mocha": "^3.1.0", "phantomjs-prebuilt": "^2.1.12", "sinon": "^1.17.6", "sinon-chai": "^2.8.0", "ts-loader": "^0.8.2", "tslint": "^3.15.1", "typedoc": "^0.4.5", "typescript": "^2.0.3", "typings": "^1.4.0", "webpack": "^1.13.2" } }
これをnpmとYarnで比較してみる。Yarnはキャッシュの効果も知りたいので1回目でコピーされたnode_modules
を削除してもう一度実行した結果もみる。
manager | time result |
---|---|
npm | npm install 44.20s user 11.06s system 28% cpu 3:11.75 total |
Yarn (1回目) | yarn 38.63s user 19.57s system 98% cpu 59.047 total |
Yarn (2回目) | yarn 23.46s user 11.32s system 116% cpu 29.961 total |
Yarnはとにかく速い。そして、Yarnは2回目でダウンロードの時間が省けるのでさらに速くなる。ちなみにキャッシュは~/.yarn-cache/
に保存されるようだ。
感想
速度が向上するのはいいことだけど、僕としてはオフラインでも作業できるようになるのが一番のメリットだと思う。 一度ローカルにnpmをミラーしようとして挫折したことがある。
とにかくYarn素敵。使わない理由はない。
GitHub - yarnpkg/yarn: 📦🐈 Fast, reliable, and secure dependency management for JavaScript.
関連記事
CPANにPerlモジュールを公開するまでの手順
CPANにAuthor登録してモジュールを公開したので、やったことを書いていく。個人的な覚書の側面が強いのであまりまとまってないかも。
ちゃんとした手順が知りたい人はQiitaとかで記事を探したほうがいいと思う。
CPAN Author登録してもらう
モジュールを公開するにはPAUSE(Perl programming Authors Upload Server)というのに登録しなければいけない。
モジュールができてからでもいいけど、npmとかRubyGemsとは違って登録作業はCPANの中の人が手動でやってるっぽいので長くて1日くらいかかる。まだ、モジュールができてない状態でもこれからどんなモジュールを公開していきたいかという抱負だけで登録してもらえるので申請だけ出しておいたほうがよい。
ツールを揃える
perlはplenv経由でインストールされている前提で書いている。揃えるべきツールは以下の3つ。
Name | Description |
---|---|
cpanm | Perlモジュールインストーラ |
Carton | モジュールプロジェクト下に依存モジュールをインストールするツール |
Minilla | モジュールの雛形を作るオーサリングツール |
インストール手順
- plenvにはinstall-cpanmというコマンドが付属しているので、これを使ってまずはcpanmをインストールする
- Cartonをインストールする
- Minillaをインストールする
$ plenv install-cpanm # (1 $ cpanm carton # (2 $ cpanm Minilla # (3
モジュールの雛形を作る
Minillaでモジュールの雛形を作る。
$ minil new <module name>
モジュール名はハイフンが入るとそこでネームスペースが切られる。例えば、saiko-no-module
とすると生成後の雛形はlib/saiko/no/module.pm
という構造を持ち、公開後のモジュール名はSaiko::No::Module
という名前になる。まあ、こんな名前をつけてはいけない。基本的にモジュール名はすでに公開されてるものを参考にしてつけるのが良い。迷ったらフォーラムで質問してもいい。Perl Mongerは優しい。
コードとモジュール情報を書く
メタ情報はMETA.json
に書いてあるが、これはMinillaが自動で生成するので直接いじらない。Minillaはコードやcpanfile
やminil.toml
から必要な情報を集めてこれを出力する。README.md
もコードのpodドキュメントから生成されるのでいじらない。
テストを走らせるには次のようにする。
$ minil test
ただ、このコマンドではgitの管理下に追加されていないテストは実行されないので、.t
ファイルを追加したらまずgit add
する。
公開する
PAUSEに登録され、コードを書いて、テストが通ったらいよいよ公開する。 公開にはPAUSEのサイトにtar.gzをアップロードするのがトラディショナルなやり方。でも、Minillaを使えばコマンドラインから公開できる。
$ minil release
その他
モジュールを公開したら、CPANのテストサーバからメールが来る。これはアップロードされたモジュールがテストを通過するかどうかを色々なプラットフォームでチェックしてくれているらしい。Travis CIとかCircle CIとかでアップロードする前にテストすることが望ましいけど、環境がubuntuのみだったりするのでBSDなんかでもテストしてくれるのはありがたい。落ちたテストレポートへのリンクが添付されているので修正に役立つ。
Travis通ったけどCPANのテストボランティアからFAILレポート来まくっててつらい
— ぬこすけ (@pg_nukosuke) October 10, 2016
関連記事
npm依存パッケージアップデートにgreenkeeper.ioが便利
今までnpm-check-updateを使ってncu -a
でアップデートをかけていたんだけど、依存を最新に保つためのgreenkeeperというサービスがあったので使ってみた。
$ npm install -g greenkeeper $ greenkeeper login $ cd ./node_project/ $ greenkeeper enable
アップデートするパッケージごとにPRを作ってくれて、そのパッケージの変更点をコメントに書いてくれる。
ちなみにウェブインタフェースもあるらしくgreenkeeper web-app
で起動できる。
無料プランではpublicリポジトリなら無制限、privateリポジトリは1つまで登録できるので積極的に使っていこう。
関連記事
言語ごとのモジュール・エコシステム事情
モダンな言語には標準でパッケージマネージャが付属することが少なくない。 これは依存関係を洗い出して開発やランタイムに必要なパッケージを自動で補完してくれるうえ、自分が作成したライブラリやアプリケーションを公開する際にも便利なユーティリティとして機能する。
いつ頃からこのようなツール群が一般的になったのかはわからないが、最近触れる機会のある言語はもれなくこの恩恵に預かっていて、それぞれの言語についてエコシステム事情が気になったので調べてみた。 触ったことがあるもの以外はあまり詳しくは書けないし間違っているかもしれない。
Ruby: RubyGems
RubyGems.org | your community gem host
数多くの言語の中でも活発なコミュニティを有するRubyはRubyGemsというエコシステムが存在する。gemやbundlerといったツールを用いて開発や実行に必要なパッケージをインストールする。依存するモジュールはGemfileというファイルに記述し、インストールするたび環境ごとの差異をなくすためGemfile.lockというファイルを生成してgemのバージョンや取得先を固定する。
JavaScript: npm
Node.jsから生まれたモジュールシステムであり、当初はサーバサイドJavaScriptであるNode.js専用のパッケージマネージャだったため、フロント側では別にbowerというマネージャが発達していた。しかし、browserifyやwebpackなどのパッキングツールの発展、サーバとフロントの両方に対応したisomorphicなライブラリの増加で近年ではbowerを投げ捨てて、npmひとつで全てを完遂するのが主流になりつつある。
Perl: CPAN
CPANはComprehensive Perl Archive Networkの略でPerlのパッケージレジストリである。このレジストリ自体は現代的なエコシステムが発達する以前から存在しており、古くはtarアーカイブをダウンロードしてインストールしたり、OS標準のパッケージマネージャを使ってモジュールをインストールしたりしていた。今では言語用のモジュールシステムの流れに乗りCPANから依存モジュールを自動で展開するツールが公開されている。自作のモジュールを公開するにはPAUSEと呼ばれる開発者用のアップロードサーバに登録する必要がある。(しかしこのPAUSE、登録申請をどうやら人力で確認しているらしく時間がかかる)
- cpanminus :: モジュールインストーラ。Rubyのgemに相当する。現在のデファクト。
- Carton :: 依存解決マネージャ。Rubyのbundlerに相当する。
- Minilla :: モジュール開発用のオーサリングツール。雛形の生成などを行う。
Perl6: Perl 6 Modules
まだ発展途上ではあるが、パッケージマネージャにはpandaというものがありmodule.perl6.orgに登録されているモジュールをインストールすることができる。 CPANのようなレジストリサーバは存在しておらずecosystem GitHubリポジトリに自らのモジュールリポジトリにあるメタデータファイルパスを追記することで公開される。
PHP: Packagist
結構前にCakePHP 2.x系を使った開発案件に携わっていたことがあるが、その頃のPHPのパッケージ管理事情は酷いものだった。そもそもまともなパッケージマネージャは存在していなかったし、エラーの原因がパッケージのバージョンなのか言語のバージョンなのかも判別が難しい状態だった。今ではcomposerというパッケージマネージャを用いるのが主流になり、ようやくこうした状況も改善された。composerはPackagistというレジストリを参照しているため、公開する際はここにモジュールのURL(GitHubなど)をsubmitする。
Python: PyPI
PyPI - the Python Package Index : Python Package Index
PythonにはPyPIというリポジトリが存在していて、インストーラとしてはeasy_installとpipがよく使われるようだ。
参考記事:Python パッケージ管理技術まとめ (pip, setuptools, easy_install, etc) (16/10/8閲覧)
Go: gopkg.in, GitHub, BitBucket, ...
Go言語はバージョン管理システムのリポジトリをそのままパッケージとして取り込むため、特定のモジュールレジストリは存在しない。そのためimport
は標準ライブラリ以外は以下のような指定になる。
import ( "github.com/hoge/huga" "bitbucket.org/hoge/huga" )
go自体にパッケージマネージャは統合されているが、go get
はデフォルトで最新のリビジョンを落としてくるため、バージョンを固定するには別途godepなどのツールを使用するかgopkg.inでバージョンを含んだURLを指定する必要がある。
Java: Maven
The Central Repository Search Engine
JavaにはMavenというツールがあり、Maven Central Repositoryというリポジトリからパッケージを取得している。最近ではGradleというビルドツールを使うことが増えているが、こちらでもMavenのリポジトリを利用することができる。
Erlang, Elixir: hex
Erlangと同じくErlang VMで動作するElixirにはhexというモジュールシステムがある。Erlangではrebar, Elixirではmixというツールを用いてパッケージマネージングを行う。
その他
CやC++など古くから存在するネイティブ言語にもあるかと思って調べてみたら一応見つかった。
C/C++ Open Source Package Manager
認知度も低く、まだ流行っているとは言い難い状況だが、普及すれば特に複雑なC/C++のライブラリ依存解決も楽になりそうだ。
参考記事:C/C++ のパッケージマネージャーである conan を使ってみた - Secret Garden(Instrumental) (16/10/8閲覧)
まとめ
- 企業が運営しているもの、コミュニティが運営しているもの、特定のレジストリを持たないものなどそれぞれ微妙に異なるが、言語ごとにエコシステムが存在している。
- 古い言語でも後からパッケージマネージャが開発されており、以前の管理方法との統合が図られている。
Alfred Gyazo Workflow作った
だいたいAlfred Workflowの作り方がわかってきたので、調子に乗ってもう一個作ってみた。
Gyazo APIのクライアントにはTomohiroさんのライブラリを使った。 前回は既存のものがなくてクライアントライブラリを書くところから始めたので結構しんどかったけど、今回はこれのおかげでめっちゃ楽だった。
GitHub - Tomohiro/go-gyazo: Go library for accessing the Gyazo API
icon(thumb nail)にリモートのURLを指定できないので、最初に全部ダウンロードして、それ以降は足りない分だけダウンロードしてキャッシュしている。
スクリーンショット共有サービスのGyazoにアップロードした画像をAlfredから取得して、
- Markdown
- HTML
- そのまま
のフォーマットでクリップボードにコピー&アクティブなウィンドウでペーストを行うワークフロー。
これ以上は作るもの思いつかないし、もういいかな。