こちらのドキュメントを見ながら、既存のRailsアプリにReactの導入を試みています。
https://github.com/reactjs/react-rails/blob/master/docs/get-started.md
- Railsにshakapackerをインストール
- yarnでReactをインストール
まで完了したのですが、ビューでコンポーネントを表示するところでつまずきました。
ActionView::Template::Error (Shakapacker can't find application.js in /Users/username/sample_app/public/packs/manifest.json. Possible causes:
1. You forgot to install javascript packages or are running an incompatible javascript runtime version
2. Your app has code with a non-standard extension (like a `.jsx` file) but the extension is not in the `extensions` config in `config/shakapacker.yml`
3. You have set compile: false (see `config/shakapacker.yml`) for this environment
(unless you are using the `bin/shakapacker -w` or the `bin/shakapacker-dev-server`, in which case maybe you aren't running the dev server in the background?)
4. webpack has not yet FINISHED running to reflect updates.
5. You have misconfigured Shakapacker's `config/shakapacker.yml` file.
6. Your webpack configuration is not creating a manifest.
Shakapackerがmanifest.jsonファイルを見つけられていないと出ています。
manifest.jsonファイルとは、Webブラウザの拡張機能を使うのに必要なファイルのようです。
Shakapackerはpublic/packsディレクトリを探しに行っていますが、そもそもpacksファイルが作られていません。
ドキュメントを遡ってみると、package.json
に"@babel/preset-react"
を追加したのですが、それを反映していないのではないかと考えました。
→package-lock.json
に追加されていたので、そうではないようです。
今回のエラーと関係があるのかわかりませんが、現在package-lock.json
とyarn.lock
がどちらもある状態になっています。
どっちを読みに行っているのかが気になりました。
どちらにも@babel/preset-react
があるので、両方読み込まれているのでしょうか?
コンパイルを実行した時にnpmが使われているので、yarn.lock
を削除してみることにしました。
(コンパイルは本番環境でやるべきことで、開発環境ではやらなくていいと後でわかりました。。)
$ rails shakapacker:compile
using npm@8.19.2 to manage dependencies and scripts in package.json
Shakapacker::Compiler - Slow setup for development
エラーの最後に「あなたのwebpack構成はmanifestを作っていませんね」と指摘されていますね。
いや、原因の1つとして挙げられているだけでした。。
2, 3, 5を見ると、どうやらconfig/shakapacker.yml
に原因がありそうな気がしてきました。
shakapacker.yml
を見てみると、以下のようになっていたので、それで/Users/username/sample_app/public/packs/manifest.json
を探しに行っているのだとわかりました。
default: &default
source_path: app/javascript
source_entry_path: packs
public_root_path: public
public_output_path: packs
manifest.json
は存在するのですが、場所が違っていて、app/assets/config/manifest.js
にありました。
shakapacker.yml
の設定を変えようかなと思ったのですが、ちょっと待てよとためらいました。
manifest.json
を通してapplication.js
を探しに行っているわけですが、application.js
が2つ存在することに気づいたからです。
いつ作られたんだっけ?と思い返してみると、
$ bundle add 'react-rails' --strict
$ rails generate react:install
react-rails
gemを追加してReactをインストールしたときに作られていました。
found 0 vulnerabilities
create app/javascript/packs/application.js
create app/javascript/packs/server_rendering.js
application.js
の中身を見てみると、Reactを呼び出しているっぽい記述があります。
Reactを使う時に呼び出すのはおそらくこっちのapplication.js
でしょう。
// Support component names relative to this directory:
var componentRequireContext = require.context("components", true);
var ReactRailsUJS = require("react_ujs");
ReactRailsUJS.useContext(componentRequireContext);
考えたこと:
探しに行っている場所にmanifest.js
を作って、その中でapplication.jsを読み込めばいい?
//= link_tree ./application.js
エラーが変わりました。書き方の問題なので、新しく作ったファイルを読みに行ってくれています。
「ディレクトリを指定しなさいよ」と言われました。
//= link_tree ../packs js
あれ?また元のエラーに戻ってしまいました。。
webpacker.ymlもあったので消しました。
この出力結果を見ると、manifest.js
が読み込まれていないですね。
Your manifest contains:
{
}
):
3.で挙がっていた開発環境でのコンパイルを試してみました。
.browserslistrc
は何のファイルでしょう?
ブラウザ設定の齟齬を解消するような役割を果たすみたいです。
要は重複しているのだろうから、.browserslistrc
を削除しました。
$ bin/shakapacker --watch
[webpack-cli] Error [BrowserslistError]: /Users/naota7118/ocr_check_app contains both .browserslistrc and package.json with browsers
at /Users/naota7118/ocr_check_app/node_modules/browserslist/node.js:369:15
at eachParent (/Users/naota7118/ocr_check_app/node_modules/browserslist/node.js:53:18)
at Object.findConfigFile (/Users/naota7118/ocr_check_app/node_modules/browserslist/node.js:347:20)
at Object.findConfig (/Users/naota7118/ocr_check_app/node_modules/browserslist/node.js:397:27)
at Function.loadConfig (/Users/naota7118/ocr_check_app/node_modules/browserslist/node.js:259:37)
at Object.load (/Users/naota7118/ocr_check_app/node_modules/webpack/lib/config/browserslistTargetHandler.js:67:19)
at getDefaultTarget (/Users/naota7118/ocr_check_app/node_modules/webpack/lib/config/target.js:19:50)
at /Users/naota7118/ocr_check_app/node_modules/webpack/lib/config/defaults.js:165:3
at F (/Users/naota7118/ocr_check_app/node_modules/webpack/lib/config/defaults.js:105:15)
at applyWebpackOptionsDefaults (/Users/naota7118/ocr_check_app/node_modules/webpack/lib/config/defaults.js:164:2) {
browserslist: true
再度コンパイルを実行すると、
ERROR in ./app/javascript/packs/server_rendering.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
Error: Cannot find package 'babel-plugin-macros' imported from /Users/naota7118/ocr_check_app/babel-virtual-resolve-base.js
webpack 5.95.0 compiled with 3 errors in 229 ms
babel-plugin-macros
というパッケージが見つからないと言われたので、npmでインストールしました。
...つもりでしたが、インストールできていないのでしょうか?
$ npm install babel-plugin-macros
added 13 packages, and audited 606 packages in 2s
78 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
この状態でRailsを再起動したら、エラーは出ずに立ち上がりました。(解決はしていませんが。。)
コンポーネントを呼び出せるようになっているかconsole.log
で確認してみると、検証画面にエラーが出ていました。
Uncaught Error: Module build failed (from ./node_modules/babel-loader/lib/index.js):
Error: Cannot find package '@babel/plugin-syntax-dynamic-import' imported from /Users/username/sample_app/babel-virtual-resolve-base.js
bable.config.js
にプラグインとして '@babel/plugin-syntax-dynamic-import'があるのですが、なぜbabel-virtual-resolve-base.js
を見に行っているのでしょう?
もしかして、 "@babel/preset-react"を追加した最新のpackage.jsonが読み込まれていない?
package.jsonを更新するため、npm updateを実行。
結果は変わらず。。
いったんここまでとします。