webpackerて何〜(前編)

今日中にエラーを討伐できなかったので前半後半に分けるという愚行をすることをお許しください。。

Herokuにデプロイを試みたときに下記エラーにハマりました。

yarn install v1.22.4
remote:        [1/4] Resolving packages...
remote:        [2/4] Fetching packages...
remote:        info fsevents@2.3.2: The platform "linux" is incompatible with this module.
remote:        info "fsevents@2.3.2" is an optional dependency and failed compatibility check. Excluding it from installation.
remote:        info fsevents@1.2.13: The platform "linux" is incompatible with this module.
remote:        info "fsevents@1.2.13" is an optional dependency and failed compatibility check. Excluding it from installation.
remote:        error eslint@8.0.0: The engine "node" is incompatible with this module. Expected version "^12.22.0 || ^14.17.0 || >=16.0.0". Got "12.16.2"
remote:        error Found incompatible module.
remote:        info Visit <https://yarnpkg.com/en/docs/cli/install> for documentation about this command.
remote:        Compiling...
remote:        Compilation failed:
remote:        yarn run v1.22.4
remote:        info Visit <https://yarnpkg.com/en/docs/cli/run> for documentation about this command.
remote:        
remote:        
remote:        error Command "webpack" not found.

ハマりましたというか、ハマっています。なので、解決はしていませんが、これを機にWebpackerを学んでみたいと思います。

追記: 上記エラーは下記コマンドで解決しました。(参考文献:https://www.bokukoko.info/entry/2017/12/07/000000)

heroku buildpacks:add --index 1 heroku/nodejs

がしかし、下記のようなエラーを吐き出してしまっています。API schemaにそぐわないオブジェクトをWebpackは使用して初期化してしまっていますね〜と吐いています。

Compilation failed:
remote:        [webpack-cli] Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
remote:         - configuration.node should be one of these:
remote:           false | object { __dirname?, __filename?, global? }
remote:           -> Include polyfills or mocks for various node stuff.
remote:           Details:
remote:            * configuration.node has an unknown property 'dgram'. These properties are valid:
remote:              object { __dirname?, __filename?, global? }
remote:              -> Options object for node compatibility features.
remote:            * configuration.node has an unknown property 'fs'. These properties are valid:
remote:              object { __dirname?, __filename?, global? }
remote:              -> Options object for node compatibility features.
remote:            * configuration.node has an unknown property 'net'. These properties are valid:
remote:              object { __dirname?, __filename?, global? }
remote:              -> Options object for node compatibility features.
remote:            * configuration.node has an unknown property 'tls'. These properties are valid:
remote:              object { __dirname?, __filename?, global? }
remote:              -> Options object for node compatibility features.
remote:            * configuration.node has an unknown property 'child_process'. These properties are valid:
remote:              object { __dirname?, __filename?, global? }
remote:              -> Options object for node compatibility features.
remote:        
remote: 
remote:  !

Webpackerって何

Webpackerは、汎用的なwebpackビルドシステムのRailsラッパーであり、標準的なwebpackの設定と合理的なデフォルト設定を提供します。

webpackをrails仕様にしたものをwebpackerというのだろうか。

まず前提として、webpackとwebpackerは別物です。webpackはJSのnpmのパッケージです。

(https://qiita.com/jesus_isao/items/1f519b2c6d53f336cadd)

ぐはっ。全くの別物なんかい。

Webpackerを構成するもの

loader

リソースをモジュール化するためのツールのこと。

webpackはモジュール化されたものをバンドルする(束ねる)ことができるツール。

画像ファイルやスタイルシートなどのリソースは、このローダーを通じてモジュール化させてあげることで、はじめてバンドルができるようになる。

(参考: https://www.fundely.co.jp/blog/tech/2020/01/22/180037/)

Babel

JavaScriptのトランスコンパイラー(変換ツール)

このBabelを介すことで、ES6(ECSAScript2015、ES2015)の標準化されたJavaScript構文を、ES6サポート対象外のIE11などでも解釈することができるようになる。

そのため、現在webpackを新しく導入する際は『webpack』と『Babel』とを組み合わせて使用するのが通例となっている。

plugin

webpackのバックボーン的な存在。

loaderのできないことを全てやってくれる。さまざまなpluginが用意されている。

Webpackのできること

  • webpackは、requireとかimportとかを解決して、IEでも読めるようにファイルをまとめ上げることができる。
  • loaderを使用することで、webpackの前処理でTypeScript → JavaScriptに変換したりもできる。
  • pluginを使用することで、webpackの後処理でJSにminifyをかけたりすることもできる。

参考:(https://qiita.com/jesus_isao/items/1f519b2c6d53f336cadd)

JavaScript」「CSS」「画像やフォント」といった静的アセットを管理できるファイルかな〜くらいにしか思っていなかったが、loaderやpluginといった記述が裏側ではなされているのか〜と知ったちなみに全く理解は出来ていない。

エラーとの戦い

先程のエラー文を調べたところ、全く同じエラーでつまづいている外国の方がいらっしゃいました。

I have encountered an error when using the latest version of Webpack (5.1.0). It looks like the configuration is throwing an error because the validation schema is too restrictive. Here is my webpack configuration file in a gist, and the error message I am seeing.

webpackの最新版を使っていて、validation の制限が厳しすぎるがためにconfigがエラーを吐いてしまっている。と書いてあります。

どうやらwebpack.config.jsの記述に誤りがあるようです。

でも、今自分が作成中のアプリにwebpack.config.jsなんてない、、

がしかし、この記事によると、webpacker.ymlがwebpack.config.jsの代わりになっているとのこと。

webpackerは、config/webpacker.ymlというwebpacker専用のymlの設定ファイルを読むことで、何をどう実行したらよいかを決定し、よしなにファイルを書き出してくれたりします。

つまり、webpacker.ymlの記述をなんとか弄ればエラーは解決できるってことか?

明日こそこのエラーを倒してherokuにデプロイをかましたいと思います。

下記参考文献を読み漁る1日にしたいです。。

Webpacker の概要 - Railsガイド

Webpack 5: configuration.node has an unknown property 'dgram'. These properties are valid: · Issue #11649 · webpack/webpack

webpack実行時にInvalid - Qiita

Webpack 5: configuration.node has an unknown property 'dgram'. These properties are valid: · Issue #11649 · webpack/webpack

GitHub - rails/webpacker: Use Webpack to manage app-like JavaScript modules in Rails

vue-loader

For example to add Vue support:

// config/webpack/rules/vue.js
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
  module: {
    rules: [
      {
        test: /\\.vue$/,
        loader: 'vue-loader'
      }
    ]
  },
  plugins: [new VueLoaderPlugin()],
  resolve: {
    extensions: ['.vue']
  }
}
// config/webpack/base.js
const { webpackConfig, merge } = require('@rails/webpacker')
const vueConfig = require('./rules/vue')

module.exports = merge(vueConfig, webpackConfig)

Getting Started | Vue Loader

webpack.config.jsがわからない - Qiita

base.js
const { environment } = require('@rails/webpacker')

const customConfig = {
  resolve: {
    fallback: {
      dgram: false,
      fs: false,
      net: false,
      tls: false,
      child_process: false
    }
  }
};

environment.config.delete('node.dgram')
environment.config.delete('node.fs')
environment.config.delete('node.net')
environment.config.delete('node.tls')
environment.config.delete('node.child_process')

environment.config.merge(customConfig);

module.exports = environment

Webpack Error - configuration.node has an unknown property 'fs'

https://gist.github.com/adarshbhat/3ec5950b66b78102da0cf46e51a3d633