LoginSignup
76

More than 5 years have passed since last update.

sprockets4にnpmを利用するための機能が追加された

Last updated at Posted at 2016-10-26

こんにちは

みんなに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します。

Gemfile
gem 'sprockets', git: 'git@github.com:rails/sprockets.git', branch: 'master'

ちなみに、現在のSprocketsの最新は4.0.0.beta4で、これにはまだnpmの機能は入っていません。
beta5になれば入ると思いますので、beta5以降は以下のように定義すれば大丈夫だと思います。

Gemfile
gem 'sprockets', '4.0.0.beta5'

2. npmパッケージをinstall

ここでは一例としてjqueryとreactをinstallします。(「その2つを同時に使うな」という話は別でやりましょう)

注: 個人的趣味によりnpmでなくyarnを使います

console
$ yarn add jquery react react-dom

このコマンドを打つと以下のファイルができます。

package.json
{
  "dependencies": {
    "jquery": "^3.1.1",
    "react": "^15.3.2",
    "react-dom": "^15.3.2"
  }
}

jqueryはnpmで管理することにしたので、Gemfileのgem 'jquery-rails'は消してしまいましょう。

3. asset管理対象にnode_modulesを入れる

Rails Guides: アセットパイプライン

config/application.rb
module SampleApp
  class Application < Rails::Application
    config.assets.paths << Rails.root.join('node_modules')
  end
end

4. npmパッケージを読み込む

app/assets/javascripts/application.js
//= 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の実装は以下の流れになっています。(コード

  1. 各npmパッケージのpackage.jsonを取得し、
  2. "main"に書かれたファイル、ないし"main"未定義の場合はindex.jsを読み込む

それを理解した上でjqueryを見てみますと、下記の画像のように"main"で指定されたファイルは"dist/jquery.js"で、これはブラウザで読めるjsになっております。

1.png

対してreactはと言いますと、"main"に書かれたファイルはnode.jsファイルのため、ブラウザで読むことができません。

2.png

ブラウザで読めるコンパイル済みファイルはdist/配下にあります。なので、直接これを//= require react/dist/reactと指定してあげる必要があります。

3.png

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界を鑑みれば落とし所としては悪くないのでは?という印象でした

追記

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
76