【爆速】Dcoker上のRailsでWebpackerのコンパイルが遅い問題を解決する方法(webpacker-dev-serverとSplitChunksの使い方)

rails-prograshi(プロぐらし)-kv Rails
記事内に広告が含まれていることがあります。

Dcoker上に構築したRailsで、Webpackerを使ってvueファイルなどをコンパイルすると、デフォルトの状態ではコンパイルにとても時間がかかります(数十秒ほど、、)

あまりにも遅すぎて、「遅い!」と叫びたくなるほどです。コーヒーを飲んだりトイレに行く機会が生まれますが全く実用的ではありません。

ここでは、コンパイル速度を劇的に改善するとても簡単な方法を2つ紹介ています。

webpack-dev-serverを使う

Railsコンテナ起動中に、コンテナの中に入りbin/webpack-dev-serverを実行します。これだけで劇的に速度が改善します。

bin/webpack-dev-server

webpack-dev-serverとは?

webpack-dev-serverはwebpackの開発サーバーを起動するコマンドです。webpackerにデフォルトで入っています。

通常のコンパイルはコンパイル結果をファイルとして出力しますが、webpack-dev-serverを使うとメモリにファイルを出力します。このため、高速化することができます。

更に、ファイルの変更を自動監視するため、変更後に保存をすると、そのタイミングでコンパイルが走ります。

とても便利な機能ですが、コンパイルのたびにメモリをどんどんと消費していくので、ファイルの変更を頻繁にすることがない本番環境では使いません。開発環境のみで使用します。

手前についている bin/ はbinディレクトリの中にある、webpack-dev-severを実行するという意味です。./bin/webpack-dev-server もやっていることは同じです。

(参考)Github webpack/webpack-dev-server


webpack-dev-serverの使用実例

既にコンテナが起動している場合や、コンテナ起動時に合わせて実行する場合などで、手順が変わるので、パターン別にまとめておきます。

Railsコンテナが既に起動している場合

Railsコンテナが既に起動している場合は、起動しているコンテナの中に入ってから、bin/webpack-dev-serverを実行します。

$ docker exec -it <Railsコンテナ名> bash
# bin/webpack-dev-server

実例

$ docker exec -it rails-vue-web bash
root@59229383d91c:/rails-vue# ./bin/webpack-dev-server

ℹ 「wds」: Project is running at http://localhost:3035/
ℹ 「wds」: webpack output is served from /packs/
ℹ 「wds」: Content not from webpack is served from /rails-vue/public/packs
ℹ 「wds」: 404s will fallback to /index.html
ℹ 「wdm」: wait until bundle finished: /packs/js/main-4c47d2a1061da7d4bba9.js
ℹ 「wdm」: Hash: 654c7ccc69cf925d0c08
Version: webpack 4.46.0
Time: 21160ms
Built at: 07/14/2021 11:10:17 AM
                                     Asset       Size       Chunks                         Chunk Names
    js/application-c4a75b572e9b964789b4.js    515 KiB  application  [emitted] [immutable]  application
js/application-c4a75b572e9b964789b4.js.map    579 KiB  application  [emitted] [dev]        application
           js/main-11b245485189537982a4.js   3.75 MiB         main  [emitted] [immutable]  main
       js/main-11b245485189537982a4.js.map   4.17 MiB         main  [emitted] [dev]        main
                             manifest.json  730 bytes               [emitted]
        media/images/mountain-83434a53.jpg    210 KiB               [emitted]
ℹ 「wdm」: Compiled successfully.

Railsコンテナ起動時に実行する場合

Railsコンテナ起動時に、bin/webpack-dev-serverを合わせて実行することもできます。

docker-compose.ymlがあるディレクトリで次のコマンドを実行します。

$ docker-compose up -d && docker-compose exec <Railsのサービス名> bin/webpack-dev-server

dオプション(detached)を使ってRailsコンテナをバックグラウンドで起動した後に、webpack-dev-serverを実行しています。

実例

$ docker-compose up -d && docker-compose exec web bin/webpack-dev-server

Starting rails-vue-db ... done
Starting rails-vue-web ... done
ℹ 「wds」: Project is running at http://localhost:3035/
ℹ 「wds」: webpack output is served from /packs/
ℹ 「wds」: Content not from webpack is served from /rails-vue/public/packs
ℹ 「wds」: 404s will fallback to /index.html
ℹ 「wdm」: wait until bundle finished: /packs/js/main-190ff4ffb5da3c8f9c01.js
ℹ 「wdm」: Hash: 654c7ccc69cf925d0c08
Version: webpack 4.46.0
Time: 12627ms
Built at: 07/15/2021 3:07:35 AM
                                     Asset       Size       Chunks                         Chunk Names
    js/application-c4a75b572e9b964789b4.js    515 KiB  application  [emitted] [immutable]  application
js/application-c4a75b572e9b964789b4.js.map    579 KiB  application  [emitted] [dev]        application
           js/main-11b245485189537982a4.js   3.75 MiB         main  [emitted] [immutable]  main
       js/main-11b245485189537982a4.js.map   4.17 MiB         main  [emitted] [dev]        main
                             manifest.json  730 bytes               [emitted]
        media/images/mountain-83434a53.jpg    210 KiB               [emitted]
ℹ 「wdm」: Compiled successfully.


注意点

dockerコンテナを、dオプション(detached)を使ってRailsコンテナをバックグラウンドで起動したときは、ctrl + c でコンテナを停止することができません。(起動し続けています)


コンテナを停止するときは、docker stop <コンテナ名1> <コンテナ名2>,,,とする必要があります。



更に効率化する(SplitChunksPluginの利用)

コンパイルを更に効率化するために、Webpacker 4では、SplitChunks(スプリットチャンクス)プラグインを使うことができます。

SplitChunksとは?メリット

SplitChunksとはWebpacker 4で使える追加機能です。

通常のコンパイルは、各ファイルに書かれている内容をそのまま出力していきます。

SplitChunksを使うと、それぞれのファイルで共通するモジュールがある場合に、各ファイルの相違点だけと、そのモジュール単体をコンパイルすることで、重複する内容のコンパイルを省くことができます。

無駄なコンパイルが発生しないので、高速化につながります。

(参考)Webpack SplitChunks Plugin

SplitChunksの導入

導入はとても簡単です。2ステップで終わります。

environment.jsの編集

config/webpack/environment.jsに次の1行を追記します。

environment.splitChunks()

これで、WebpackerにSplitChunksを使うことを宣言できます。

実例

const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const vue = require('./loaders/vue')

environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())
environment.loaders.prepend('vue', vue)

environment.splitChunks() //追記

module.exports = environment

タグの変更

SplitChunksでコンパイルしたファイルを呼び出すために、呼び出し用のタグを変更する必要があります。

javascript_pack_tagjavascript_packs_with_chunks_tag に変更します。

実例

<%= javascript_pack_tag 'main' %>
<%= stylesheet_pack_tag 'main' %>

   ↓

<%= javascript_packs_with_chunks_tag 'main' %>
<%= stylesheet_packs_with_chunks_tag 'main' %>

以上でSplitChunksの設定は完了です。後はコンパイルすれば、SplitChunksで生成したファイルを使ってブラウザを描画します。

(参考)SplitChunksの確認

SplitChunksが正しく機能しているか確認します。Chromeの開発ツールのSourceタブで読み込んでいるファイルを見ると分かりやすいです。

デフォルトの状態

デフォルトの状態では、.jsというファイルを読み込んでいます。

SplitChunks利用時

SplitChunks利用時は、chunk.jsというファイルも読み込んでいます。

SplitChunksが正しく機能している状態です。

タイトルとURLをコピーしました