1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Webpackを知る

Last updated at Posted at 2021-08-29

なぜ書くのか?

先日、railsのViewで謎のpadding-top:60px;に出くわした。検証ツールでみるに、reboot.cssの46行目と書いているが、reboot.cssの中をみてもない。自分のファイルにもそんな記述はない。どうして?色々模索し、先輩エンジニアさんに質問させていただいたところ、以前のscssファイルに書いたpadding-top:60px;が残り、使われていることがわかった。つまり、現在の最新の状態のscssが読み込まれていなかったそう。どうして、読み込まれていなかったのか?それは、どうやら問題はwebpackにあるようである。

Webpackとは?

Webアプリケーションの装飾に必要なCSS、JavaScript、画像などを1つのファイルとしてまとめるためのモジュールバンドラーで、node.jsのモジュールの1つ。従来、使用するjavascriptファイルを個別で指定していために、表示に時間がかかったり、ファイルの指定を手動で行うために、ミスが発生しやすかった。その問題を解決したのがWebpack。対象のファイルを自動で検出し追加してくれるため、手動によるミスの発生や不適切な順序でファイルが実行されてしまう心配がなくなり、また、時間の高速化にもつながった。

Webpackerとは

WebpackerとはWebpackをRuby on Railsで使うためのgemパッケージ。webpackを良い感じに動かしてくれる優れもの。

Webpackメリットを整理

依存関係のあるJavaScriptのモジュールを解決

ファイル間の依存関係を解析して1つのファイルにまとめてくれるので、保守性が高くなり他のプロジェクトにもファイルを転用しやすくなる。

ファイル読み込みが効率化

ブラウザとウェブサーバーの同時接続数が限られるため、複数のファイルがあると転送に時間がかかる。ファイルを一つにまとめることで、リクエスト回数を減らすことができ、サーバーの負担が少なくなり高速化することができる。

CSSや画像をJavaScriptで扱う

ローダを使えば、HTMLやCSSファイルなど、JavaScript以外のファイルをJavaScriptで扱うことができます。また、画像をDataURLに変換処理したり、コードをチェックしたりすることもできる。

http2とwebpackの関係

HTTP/1.1では同一のホスト名に対して同時にリクエストできる数には制限があるために、複数のスクリプトファイルをwebpackBrowserifyといったバンドルツールを用いて結合させるのが一般的だった。HTTP/2ではリクエストとレスポンスのストリームが多重化されている。並列して複数のリクエストを送信できるようになったため、これまで当たり前のことであったスクリプトファイルの結合の必要性は薄くなった。しかしながら、http2に置いても二つの点からwebpackを使用するメリットがある

ストリーム数には制限がある

ほとんどのサーバーでは、接続時に送信されるSETTINGSフレームの中で、同時ストリーム数を100などの妥当な値に制限している。これは、100以上の同時リクエストを発行できないことを意味しており、例えば、数百のjsファイルを持つ大規模なアンバンドルReactアプリを持っている場合には問題となる

js間の依存関係をバンドルする

javascript ファイル間には推移的な依存関係があり、http2のようにすべての依存関係をバンドルしていない場合、ブラウザは以前のレスポンスを受信したときにのみ依存関係を発見するため、多くのリクエストラウンドトリップが必要となる。

これらの理由から、webpack を使用していくつかの同種のバンドルをパッケージ化し、最大同時リクエスト数がサーバーの制限を超えないようにする一方で、効率的なブラウザキャッシングを活用するためにバンドルの粒度を十分に保つ。
参考記事

webpackerをRailsアプリケーションに導入

rails6以降は、標準でwebpackerが導入されているが、それ以前のverの場合の既存のアプリにはbin/rails webpacker:installを使用する。またwebpackerは、yarnに依存するために、yarnを事前にインストールする。Webpackerをインストールすると、デフォルトではapp/javascripts/packsディレクトリ以下のJavaScriptファイルがコンパイルされて独自のpackファイルにまとめられる。

例えば私の場合、app/javascript/packs/application.jsというファイルができ、Webpackerはapplicationという名前のpackを作成する。そしてこのpackは、<%= javascript_pack_tag "application" %>というERBコードで指定し使用する。またすべてのERBで、webpackerの機能を使いたいので、application.html.erbの headタグ内に記載する。

CSSや画像の場合

What Webpacker
JavaScriptをアタッチする javascript_pack_tag
CSSをアタッチする stylesheet_pack_tag
画像にリンクする image_pack_tag

css フレームワークを使う

1. application.html.erbの headタグ内に、<%= stylesheet_pack_tag "application" %>、を追加
2. yarn add <フレームワーク名>

railsアプリケーションにbooststrapを導入

  1. yarn add jquery bootstrap popper.js

  2. 必要なモジュールを、グローバル変数に代入する

config/webpack/environment.js
// jQueryとBootstapのJSを使えるように
const webpack = require('webpack')
environment.plugins.prepend(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    Popper: 'popper.js'
  })
)
  1. bootstrapをimport
app/javascript/stylesheets/application.scss
@import '~bootstrap/scss/bootstrap';

import 'bootstrap'とせずに、必要に応じて個別にプラグインをインポートすることで、無駄を削除

4.bootstrapと、application.scssをimport

app/javascript/packs/application.js
import 'bootstrap';
import '../stylesheets/application';

webpackのエントリーファイルだけを置く

ここで重要なのが、app/javascript/packsディレクトリにはwebpackのエントリーファイルだけを置き、それ以外のものを置かないことが重要。application.*だけ

app/javascript:
  ├── packs:
  │   # ここにはwebpackエントリーファイルだけを置くこと
  │   └── application.js
  │   └── application.css
  └── src:
  │   └──〇〇.js
  └── stylesheets:
  │   └── ▲▲.css
  └── images:
      └── ■■.png

構成を変更したい場合

構成を変更したい場合は、config/webpacker.ymlを書き換える。config/webpacker.ymlには、エントリーポイントやdevelopやproduction固有の設定を定義している。

config.yml
default: &default
  source_path: app/javascript # pathを書き換える、以下も同様に
  source_entry_path: packs
  public_root_path: public
  public_output_path: packs
  cache_path: tmp/cache/webpacker
  webpack_compile_output: true
  ...続く

ビルドしてみる

bin/webpackを実行

% bin/webpack
Hash: 5e57f23ab887a258f576
Version: webpack 4.46.0
Time: 5572ms
Built at: 2021-05-01 17:17:56
                                     Asset       Size       Chunks                         Chunk Names
    js/application-7cad38888ab4f4a77a4e.js   1.27 MiB  application  [emitted] [immutable]  application
js/application-7cad38888ab4f4a77a4e.js.map   1.39 MiB  application  [emitted] [dev]        application
                             manifest.json  364 bytes               [emitted]              

app/javascript/packs/application.jsがビルドされて public/packs/ に application.jsとapplication.js.mapというファイルが生成される

.mapて?

.map拡張子はSourceMapといい、コンパイル前とコンパイル後の対応関係を記したファイルである。Json形式で記述されている。ブラウザーが元のソースを再構成して、そのソースをデバッガーに提供することで、デバックをしやすくするらしい。

bin/webpackでビルドしたjsをインクルードするために、javascript_pack_tag を使用する。これで、なんとなく流れは理解。

さらに便利にビルドする

bin/webpack-dev-serverこのコマンドとrails sをしてサーバーを動かすと、JS側の変更をホットリロードしてくれるので開発が快適に!下記のようになるので、成功したかもわかりやすい。

<中略>
ℹ 「wdm」: Compiling...
ℹ 「wdm」: Compiled successfully.
# :を抜いた
ERROR
>>     padding-top 60px;
   ----^

最後に

padding-top: 60px;を消したい!という気持ちから、多くのことを学べた。今までの自分なら、絶対に padding-top: 0px !important;などと書いたり、あるいは無視したりしていた。近道をしていたら必ずまた同じ問題に遭遇し、その度適当にこなしていたら、どんどん複雑で無駄の多い汚いコードになる。中々課題の進捗はないが、今日もまた昨日より新しい知識を手に入れた。着実に確実に積み上げていきたい。

1
0
0

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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?