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

webpackerからshakapackerへの移行方法

Posted at

背景

webpackerの開発が終了しており、後継であるshakapackerへの移行をする必要があります。

しかしながら、webpackerからshakapackerへの移行方法については、ネット記事が多数存在しますが、個別具体性が高く効率的に移行を進めることは困難でした。

そこで、本記事ではwebpackerからshakapackerへの移行に関する私の記録を残します。

本記事も個別具体性が高いかもしれませんが、これからwebpackerからshakapackerへの移行を試みる方々の参考になれば嬉しいです。

バージョン

Ruby:3.2.4
Rails:6.1.7.7
bundler:2.5.3
node:22.11.0
npm:10.9.0
yarn:4.0.0
webpack:4.46.0

※shakapackerは、yarn3系もしくは4系と互換性があります。shakapackerのインストール前に、yarnのバージョンを更新しておきましょう。

※webpacker利用者の中にはnode18系を利用している方も多いかと思います。shakapackerへの移行を機に、node22系に更新しましょう。

開発環境

macOS: Sonoma14.7.1
エディター: Cursor@VSCode

webpackerからshakapackerへの移行手順

1. shakapackerのインストール

公式ドキュメントを参考にして、shakapackerをインストールします。

bundle add shakapacker --strict
./bin/bundle install
./bin/rails shakapacker:install

2. webpackerの削除

以下のコードにより、webpackerを削除します。

bundle remove webpacker
yarn remove @rails/webpacker

必要なBabelをインストールし、webpack-dev-serverを削除します。

yarn add @babel/core @babel/plugin-transform-runtime @babel/preset-env @babel/runtime babel-loader compression-webpack-plugin terser-webpack-plugin webpack webpack-assets-manifest webpack-cli webpack-merge
yarn add -D webpack-dev-server

3. webpack.config.jsの修正

webpack.config.jsは2種類存在します。

①プロジェクトファイル直下のwebpack.config.js
②app>config>webpack直下のwebpack.config.js
※webpack.config.jsが存在しない場合は、新規でファイルを作成してください。

プロジェクト直下のwebpack.config.js(①)は通常、shakapackerとは無関係で、独立したwebpackプロジェクト用に使用されることが多いです。

shakapackerは、webpackの設定ファイルとしてconfig/webpack/webpack.config.js(②)を使用します。

参考までに、プロジェクト直下のwebpack.config.js(①)とconfig/webpack/webpack.config.js(②)のコードは以下のとおりです。

# プロジェクト直下のwebpack.config.js(①)

const { env, webpackConfig, merge } = require('shakapacker') // shakapackerからmergeをインポート
const { existsSync } = require('fs')
const { resolve } = require('path')
const webpack = require('webpack') // Webpackをインポート

// CSS関連の設定
const cssConfig = {
  resolve: {
    extensions: ['.css', '.scss', '.sass'], // CSSやSASSファイルの拡張子を解決
  },
}

// 環境ごとの設定を読み込む関数
const envSpecificConfig = () => {
  const path = resolve(__dirname, `${env.nodeEnv}.js`)
  if (existsSync(path)) {
    console.log(`Loading ENV specific webpack configuration file ${path}`)
    return require(path)
  } else {
    console.log(`WARNING: Using default webpack configuration. Did not find a Env specific file at path ${path}`)
    return {}
  }
}

// 共通設定(以前のenvironment.jsから移行)
const commonConfig = {
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery/src/jquery',
      jQuery: 'jquery/src/jquery',
    }),
  ],
}

// 環境ごとの設定、共通設定、CSS設定をマージ
module.exports = merge(webpackConfig, commonConfig, cssConfig, envSpecificConfig())
# app>config>webpack直下のwebpack.config.js(②)

// See the shakacode/shakapacker README and docs directory for advice on customizing your webpackConfig.
const { generateWebpackConfig } = require('shakapacker');
const { merge } = require('webpack-merge'); // webpack設定をマージするためのライブラリ
const webpack = require('webpack');
const path = require('path');

// 基本的なWebpack設定を生成
const webpackConfig = generateWebpackConfig();

// jQueryをグローバルスコープに提供するための設定
const customConfig = {
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery', // `$`としてjQueryを使用可能に
      jQuery: 'jquery', // `jQuery`として使用可能に
      jquery: 'jquery', // `jquery`としても使用可能に
      Popper: ['popper.js', 'default'], // 必要に応じてPopper.jsも追加
    }),
  ],
};

// エントリポイントを追加(既存コード)
webpackConfig.entry = {
  application: path.resolve(__dirname, '../../app/javascript/application.js'),
  maps_autocomplete: path.resolve(__dirname, '../../app/javascript/maps_autocomplete.js'),
};

// Shakapackerの基本設定とカスタム設定をマージしてエクスポート
module.exports = merge(webpackConfig, customConfig);

補足① プロジェクト直下のwebpack.config.js(①)について

以下のコードが、environment.jsの役割を担っています。したがって、environment.jsファイルを削除します。

// 環境ごとの設定を読み込む関数
const envSpecificConfig = () => {
  const path = resolve(__dirname, `${env.nodeEnv}.js`)
  if (existsSync(path)) {
    console.log(`Loading ENV specific webpack configuration file ${path}`)
    return require(path)
  } else {
    console.log(`WARNING: Using default webpack configuration. Did not find a Env specific file at path ${path}`)
    return {}
  }
}

補足② app>config>webpack直下のwebpack.config.js(②)について

アプリのjsファイルではjQueryを使用しています。そのため、以下のコードのように「jQueryをグローバルスコープに提供するための設定」をコーディングしています。

const customConfig = {
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery', // `$`としてjQueryを使用可能に
      jQuery: 'jquery', // `jQuery`として使用可能に
      jquery: 'jquery', // `jquery`としても使用可能に
      Popper: ['popper.js', 'default'], // 必要に応じてPopper.jsも追加
    }),
  ],
};

jsファイルは「app>javascript>application.js」の他にも、「app>javascript>maps_autocomplete.js」が存在します。maps_autocomplete.jsは個人的にカスタマイズしているファイルです。maps_autocomplete.jsをapplication.jsに統合するとシンプルになりますが、maps_autocomplete.js内のコード(主にGoogleMap表示関連のコード)は別管理したいので、以下のコードのようにエントリポイントを設定しています。

// エントリポイントを追加(既存コード)
webpackConfig.entry = {
  application: path.resolve(__dirname, '../../app/javascript/application.js'),
  maps_autocomplete: path.resolve(__dirname, '../../app/javascript/maps_autocomplete.js'),
};

4. development.js, test.js, production.jsの修正

development.js, test.js, production.jsのコードは、以下のとおりです。必要に応じてカスタマイズしてください。

const { webpackConfig } = require('shakapacker')

// 必要に応じてカスタマイズを追加
// 例: webpackConfig.devtool = 'cheap-module-source-map'

module.exports = webpackConfig

5. webpacker.ymlからshakapacker.ymlを作成する。

config>webpacker.ymlをもとに、
config>shakapacker.ymlを作成します。

私の場合はPerplexity(chatGPTでもたぶん大丈夫です)に『現在の「webpacker.yml」のコードは以下のとおりです。このコードをshakapacker.ymlのコードに修正してください。』と依頼、shakapacker.ymlのコードを生成しました。

# config>shakapacker.yml

default: &default
  source_path: app/javascript
  source_entry_path: /
  public_root_path: public
  public_output_path: packs
  cache_path: tmp/cache/shakapacker
  webpack_compile_output: true
  nested_entries: false

  # Additional paths webpack should lookup modules
  # ['app/assets', 'engine/foo/app/assets']
  additional_paths: []

  # Reload manifest.json on all requests so we reload latest compiled packs
  cache_manifest: false

  # Extract and emit a css file
  extract_css: false

  static_assets_extensions:
    - .jpg
    - .jpeg
    - .png
    - .gif
    - .tiff
    - .ico
    - .svg
    - .eot
    - .otf
    - .ttf
    - .woff
    - .woff2

  extensions:
    - .jsx
    - .mjs
    - .js
    - .sass
    - .scss
    - .css
    - .module.sass
    - .module.scss
    - .module.css
    - .png
    - .svg
    - .gif
    - .jpeg
    - .jpg

development:
  <<: *default
  compile: true

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: false
    host: localhost
    port: 3035
    public: localhost:3035
    hmr: false
    # Inline should be set to true if using HMR
    inline: true
    overlay: true
    compress: true
    disable_host_check: true
    use_local_ip: false
    quiet: false
    pretty: false
    headers:
      'Access-Control-Allow-Origin': '*'
    watch_options:
      ignored: '**/node_modules/**'

test:
  <<: *default
  compile: true

  # Compile test packs to a separate directory for testing purposes.
  public_output_path: packs-test

production:
  <<: *default

  # Production depends on precompilation of packs prior to booting for performance.
  compile: false

  # Extract and emit a CSS file for production builds.
  extract_css: true

  # Cache the manifest.json for performance in production.
  cache_manifest: true

なお「nested_entries: false」は必ず設定してください。app>javascript直下のファイルのみを対象とするためです。「nested_entries: false」を設定しないと、app>javascript配下のサブディレクトリも全て対象となってしまいます。

shakapacker.ymlでは「source_entry_path: /」を設定します。このタイミングで、app>javascript>packs配下のファイルを、app>javascript配下に移動します。

6. package.jsonの修正

package.jsonに以下のコードを書いてください。

"browserslist": [
  "defaults"
]
"babel": {
  "presets": [
    "./node_modules/shakapacker/package/babel/preset.js"
  ]
}

「"./node_modules/shakapacker/package/babel/preset.js"」が重複で書かれている場合がありますが、重複は避けましょう。

次いで、プロジェクト直下の「.browserslist」を削除しておきます。

7. cssおよびsassの設定

以下のコードを実行します。

yarn add css-loader style-loader mini-css-extract-plugin css-minimizer-webpack-plugin sass sass-loader

8. コンパイルの実行

以下のコードを実行します。

bin/rails assets:clobber assets:precompile

9. 古いbinstubの削除

以下のコードで、古いbintubをgitの対象外とします。

git rm bin/webpack bin/webpack-dev-server

10. webpackerのヘルパーの修正

「javascript_pack_tag」と「stylesheet_pack_tag」は、各ファイルに一度しか使えません。基本形は、公式ドキュメントのとおりです。

<%= javascript_pack_tag 'application' %>
<%= stylesheet_pack_tag 'application' %>

私の場合は、「application.html.erb」で「application.js」と「maps_autocomplete.js」の2つのファイルを読み取る必要がありました。

コーディングは、以下のとおりです。

<%= javascript_pack_tag 'application', 'maps_autocomplete', type: 'module', 'data-turbolinks-track': 'reload' %>

「'data-turbolinks-track': 'reload'」が必要かは不明ですが、念のため、webpacker使用時のコードを残しています。

※画像パスも「asset_pack_path('media/images/hoge')」から「asset_pack_path('static/hoge')」に修正する必要があるかもしれませんので、ご注意ください。

11. サーバーの起動

最後に「bin/rails s」で、サーバーを立ち上げてみてください。

まとめ

webpackerからshakapackerへの移行方法を紹介させていただきました。

コンパイル時にエラーが発生したりして、やってみると結構大変です。

エラーに関しては、Perplexityを多用すると解消できます。しかしながら、細かいことまで自分で理解していかないと解消しきれないエラーも出ますので、ゆっくりでもいいので確実に移行を進めてみましょう!

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