CTC 教育サービス
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes
こんにちは。アプリケーションを作るときには、様々な技術の取捨選択を行いますよね。たとえば、フロントエンドの実現に使う技術(React、Vue、Angular、jQueryなど)の選択です。私も、これまでに何度も何度も類似技術の調査をして、比較表を作り、上司やチームメイトに提案してきました。その度に、「すでにどこかに要点をまとめたサイトがないものか」と思っていました。
今回紹介する記事は、WebpackerとSprocketsを比較検討するものです。少し長いかもしれませんが、選択に悩んでいるかたは是非お読みください。
なぜRails 6にはWebpackerとSprocketsの両方が含まれているのでしょうか?
Why does Rails 6 include both Webpacker and Sprockets?
https://rossta.net/blog/why-does-rails-install-both-webpacker-and-sprockets.html
ネタバレ:DHHがそう言っているから・・・ですが、自分で選ぶことも可能です。
この投稿を読んでいるみなさんはすでに、Rails 6ではWebpackerとSprocketsの両方がインストールされるということをご存じで、これがWTFになっているのかどうかが気になっているのではないでしょうか。ちなみに、こちらがRailsのすべてのMay of WTFsです。
あなたがもしこのように考えていたとしても、それはあなただけではありません。
こちらのRedditの投稿 や、こちらのStackOverflowの質問、またはこちらの別のRedditの投稿のように、同じ質問が増え続けています。
私の同僚の@danmayerはこのようにツイートしています。
https://twitter.com/danmayer/status/1258577270760804353
@avdiも先週このようにツイートしています。
https://twitter.com/avdi/status/1256742291890413570
WebpackerとSprocketsの共存が多くの人を驚かせていることは明らかですが、それには理由もあります。
Sprocketsとwebpackが、「ブラウザー用のアセット(JavaScript、CSS、画像、フォント)のパッケージ化」という同じ課題を解決するという考えは間違いありません。
Sprocketsとwebpackには次の類似点があります。
ただし、Sprocketsとwebpackのアセットのバンドル方法は非常に異なります。
Sprocketsが発表されたのは2007年(!)で、Node.jsの前、JavaScriptのカンブリア爆発の前、CommonJS、AMD、EcmaScriptモジュールなどのモジュール仕様の前、webpack、browserify、$SONOTA_NO_MODULE_AWARE_ASSET_BUNDLERの前です。Sprocketsは、JavaScriptコミュニティの他のプロジェクトのように、ツールや、言語機能、ブラウザー機能(ソースマップ用の保存)の改善に追いついていません。
一方、WebpackはJavacriptモジュールの概念を完全に取り入れていて、BabelやPostCSSなど、ほぼすべての最近のWebフレームワークを統合します。コード分割のための動的インポートなど、多くのモジュール構文をサポートしています。さまざまな設定用のソースマップオプションもあります。何から何まで、webpackのコンパイルプロセスは常にモジュール化されており、カスタマイズが可能になっています。
Rails 5.1で推奨されるJavaScriptコンパイラーとして、Webpackが最初に導入された2016年に、DHHが簡潔でシンプルな答えを出しています。
https://twitter.com/dhh/status/808349072734027776
まばらなJavaScriptや、静的ファイルのCSSや画像などには引き続きアセットパイプラインを使用します。2つのアプローチは共存できます。
この決定について詳しく説明すると、WebpackerをRails 6のデフォルトのJavaScriptコンパイラにするためのGitHubのDHHのプルリクエストで、DHHが次のような返答をしていました。(github.comサイト)
@dwightwatson 興味本位なのですが、CSSや静的アセットはWebpackerがデフォルトでサポートしているのに、Sprocketsを使用し続ける根拠は何ですか?
@dhh 個人的な意見ですが、Webpackのサポートはぎこちなく、Sprocketsに勝るメリットがありません。JavaScriptコンパイルの分野とは違うのです。
紐解くべきものがたくさんあります。
アセットのバンドルに関しては、「Rails的な方法」では、JavaScriptはWebpackで、他のものはSprocketsで扱います。Basecampが使用するものと同様の、Rail 6の新規インストールでのデフォルトのセットアップは、CSS、画像、フォントをSprocketsでコンパイルします。
つまり、Basecampのメンバーであれば、すべてのwebpack JavaScriptのソースファイルは app/javascript
にあり、すべてのSprockets CSSと画像は app/assets
に残りますが、rails assets:precompile
を実行すると、最初にすべてのSprocketsアセットが public/assets
ディレクトリにビルドされ、次にすべてのwebpackアセットが public/paks
ディレクトリにビルドされます。
明確にしておくと、これはブラウザにアセットを提供するためにSprocketsとWebpackerの両方を実行する必要があるという意味ではありません。アセットをバンドルする2つのプロセスは完全に分離されており、依存関係を共有しません。異なるヘルパー、異なる実装、異なるディレクトリ、すべて異なります。これらは、Railsアプリケーショと共存できるように構築されています。
一方、すべてのアセットをまとめてバンドルするには、SprcketsまたはWebpackerのどちらか一方のみを使用します。
DHHは、JavaScript以外のアセットを扱うwebpackのアプローチを「変な感じがする(awkward)」と言っていますが、今、私はたまたまWebpackが好きですが、しかし、彼も間違ってはいません。
彼がこう述べる理由は、CSSと画像をwebpackにバルするために、JavaScriptファイルからCSSと画像をインポートする必要があるからです。
import '../application.css'
import myImageUrl from '../images/my-image.jpg'
webpackはすべてをJavaScriptモジュールとして扱いたがっています。「すべて」をです。
JavaScriptのすべてのインポートはJavaScrptモジュールとして扱われます。CSSをwebpackで使用するためにも、JavaScriptモジュールと同じようにインポートします。特にSprocketsの経験者から見ると、これは珍しく映ることでしょう。
これは単に「Rails的な意見」ではありません。Reactコミュニティの著名人であるRyan Florenceのこちらのツイートを考えてみてください。
https://twitter.com/ryanflrence/status/1258966331572928514
逆にSprocketsの良さを理解しているかのように聞こえますか? (私はフィフティーフィフティーに割れたことに驚きません)。
一部の人には変な感じがするかもしれませんが、webpackの「すべてがモジュール」という考え方は非常に強力です。ツールがそのようなメンタルモデルに完全に適合すれば、興味深い可能性が出てきます。「すべてがオブジェクト」の考えがRubyに何をもたらしたのかを考えてみてください。
良いニュースは、これについて心配する必要がないことです。RailsのデフォルトはBasecampチームの推奨アプローチを反映していますが、だからといってあなたがこれに賛同する必要もなければ、これがアプリケーションを作る正しい方法であるわけでもありません。Basecampのように両方を使用することもできますし、どちらか一方を選択することもできます。
みなさんの判断を助けるために、react-raisプロジェクトにあるこちらの素晴らしいガイドを持ってきました。
適切なJavaScriptモジュールシステムを使用して依存関係を管理したい。つまり、グローバルスコープの汚染を制限し、import/exportとrequireで明示的な依存関係グラフを作成したい
ES6以上、Babel、PostCSSの最新機能を活用したい
動的インポートやwebpackのsplitChunks最適化などのインテリジェントなコード分割機能が欲しい
ビルドシステムがソースマップを生成する方法に柔軟性を持たせたい
ホットモジュールリプレイスメント(HMR)など、ローカル開発用の高度なツールが欲しい
シングルページアプリを構築したい*
webpackを使用するためにシングルページアプリを用意する必要はありません。「マルチページアプリ」でも非常にうまく機能します。
Sprocketsはもう過去のものにしたいです。Sprocketsが最初に導入されたときはアセットマネジメントを大きく飛躍させましたが、今はもう新技術を活用していません。コードの分割によるパフォーマンスの最適化など、webpackの主要な機能はファーストクラスなのに、Sprocketsは衰退しています。
Webpackはより複雑で、いくらかの投資が必要ですが、私にとって、その価値はありました。
JavaScriptが大量にあるアプリケーションにはwebpackが良い選択肢だと思います。
みなさんはどちらが合いますか?
[IT研修]注目キーワード Python UiPath(RPA) 最新技術動向 Microsoft Azure Docker Kubernetes