こんにちは
みんなにdisられて久しいsprockets氏ですが、面白そうなコミットが入っていたので紹介します
https://github.com/rails/sprockets/commit/6eac004a1567f70270606170f8a4d51d4e2fb3e8
どんなコミット?
sprocketsからnpmパッケージを利用するための機能が追加されました。
これにより、例えばこれまでjquery-railsなどjsをラップしたgemを用いていたものを、npmで管理できるようになります。
この変更は何が嬉しいの?
この変更により、npmの世界でjsライブラリを管理する道が整備されました。
なぜ道が整備されたことを強調するかと言いますと、別にこれまでもbrowserify-rails/webpack-railsなどを利用すれば同じことが出来たからです。
ただ、「Railsが公式にnpmでのパッケージ管理を行う道を整備した」ことは、以下のような状況と比較して大いに価値があることだと思っています。
- エッジなjsを使いたい人は、独自に頑張らなければならなかった
- 導入/維持コストが馬鹿にならない
- 車輪の再発明
- 頑張れない状況の人はxxjs-rails gemなどを利用しなければならなかった
- JSをRubyの世界で管理しなければならない
- バージョンアップデートつらい
- JSの進化についていけない
今すぐ使いたい方々のための導入ガイド
1. sprockets4をinstall
Gemfileに以下の行を追加して、bundle install
します。
gem 'sprockets', git: 'git@github.com:rails/sprockets.git', branch: 'master'
ちなみに、現在のSprocketsの最新は4.0.0.beta4で、これにはまだnpmの機能は入っていません。
beta5になれば入ると思いますので、beta5以降は以下のように定義すれば大丈夫だと思います。
gem 'sprockets', '4.0.0.beta5'
2. npmパッケージをinstall
ここでは一例としてjqueryとreactをinstallします。(「その2つを同時に使うな」という話は別でやりましょう)
注: 個人的趣味によりnpmでなくyarnを使います
$ yarn add jquery react react-dom
このコマンドを打つと以下のファイルができます。
{
"dependencies": {
"jquery": "^3.1.1",
"react": "^15.3.2",
"react-dom": "^15.3.2"
}
}
jqueryはnpmで管理することにしたので、Gemfileのgem 'jquery-rails'
は消してしまいましょう。
3. asset管理対象にnode_modulesを入れる
module SampleApp
class Application < Rails::Application
config.assets.paths << Rails.root.join('node_modules')
end
end
4. npmパッケージを読み込む
//= require jquery
//= require react/dist/react
//= require react-dom/dist/react-dom
ここでちょっと面倒な話なのですが、コード例のようにjqueryは//= require jquery
でrequireできますが、
reactやreact-domでは//= require react
ではなく//= require react/dist/react
と書く必要があります。
これはなぜかと言いますと、各パッケージのpackage.jsonの"main"
に書かれたjsファイルが「ブラウザで読めるjs」か「node.js(CommonJS)のjs」かの2通りあるためです。
これについて、もう少し詳しく見ていきます。
まず、sprokects/npmの実装は以下の流れになっています。(コード)
- 各npmパッケージのpackage.jsonを取得し、
- "main"に書かれたファイル、ないし"main"未定義の場合はindex.jsを読み込む
それを理解した上でjqueryを見てみますと、下記の画像のように"main"
で指定されたファイルは"dist/jquery.js"で、これはブラウザで読めるjsになっております。
対してreactはと言いますと、"main"
に書かれたファイルはnode.jsファイルのため、ブラウザで読むことができません。
ブラウザで読めるコンパイル済みファイルはdist/
配下にあります。なので、直接これを//= require react/dist/react
と指定してあげる必要があります。
require
してみてうまくいかなかった時にnode_modules
を確認しに行けばいいだけとはいえ、これが少々面倒で何かうまい感じにならないかなー、と思っています。
が、それを置いておけばこれだけでnpmパッケージをsprocketsで利用できます!
実際に動くサンプルアプリも作りましたので、動かしてみたい方はどうぞ
https://github.com/itkrt2y/sprockets4-sample
所感
Pros
- 手軽にnpmを利用できるようになる
- Ruby層でのJSパッケージ管理をやめて、JS層に持ってこれる
- Railsでのnpmの使い方を公式が提供してくれたことにより、車輪の再発明が減る
Cons
sprocketsを使う以上、前からずっとある問題ですが......
- Railsを起動しない、JSのみの単体テストをすることができない
- やっぱりCommonJS欲しい
- globalにライブラリが読み込まれてしまう......
- JSガチ勢の利用には耐えなさそう......
まとめると、sprockets故の苦しみは解消されていないのですが、現状のJS界を鑑みれば落とし所としては悪くないのでは?という印象でした
追記
rails newする際にnpm用の設定を生成する提案も行われていて、色々と動いてはいる / Add npm support in new apps using --npm option https://t.co/rvuzrgsJjU
— 神社 (@y_yagi) 2016年10月26日