問題
自作したReact Componentを含むnpmライブラリを、NextJsプロジェクトでinstall、next buildしたところ、Cannot find module 'project\node_modules\react\jsx-runtime' imported from project\node_modules\my-library\my-component Did you mean to import react/jsx-runtime.js?というエラーが発生しました。
Stack Overflowなどでも取り上げられており、ライブラリとプロジェクト間のVersion差異で、簡単に解決できるかなぁと思ったところで見事沼にはまりました。
まず、試したのは以下です。
Reactを最新Ver18に上げるという手段はプロジェクトへの影響上除外しています。
-
@types/reactを最新Verにあげるライブラリ側も、Nextjsプロジェクト側も全てVersionを揃えてみましたが、改善しませんでした。プロジェクト側で問題なく
@types/reactによるModue resolutionは行えていたので望み薄だったので気にしません。 -
node_modulesと.lockファイルを削除し、installlockファイルを削除するという荒業ですが、やるしかありません。
package.jsonの各ライブラリVersionを色々と調整しつつ、やっとの思いで試してみましたが、改善しません。
単純な問題ではないことが分かり、色々と覚悟すると共に、「調子にのってライブラリなんて作るんじゃなかった」などの後悔も当然発生します。手がかりはエラーメッセージのみです。
環境
以下で完全に再現というわけではなく、関連するパッケージのみ上げています。
※ちなみにreact:17.0.2は、こちら記載のjsx-runtimeによるJSX解析を行います。
-
npmライブラリ
react:17.0.2
typescript:4.4.4 -
NextJs Project(上記Packageをインストールする)
react:17.0.2
typescript:4.4.4
原因
エラー発生元は、npmライブラリの実ファイル、つまりバンドル後のJavaScriptから発生しており、この時点で@types系の問題ではないことが分かりました。
つまり、本来はreact/jsx-runtimeという名称そのままでインポートされるべきということです。
ここで、npmライブラリを作成したときの知恵が役立ちます。
parent/childのような形式で、モジュールインポートを行えるようにするには、reactライブラリのpackage.jsonに以下のような記載が必要です。パスを明示的に設定する必要があります。
{
"name":"react",
,
,
"exports": {
"./jsx-runtime":{
"import": "xxxx",
"require": "xxx"
}
}
}
プロジェクト側のnode_modules/reactのpackage.jsonを確認してみると、exportsの記載がありません!
この問題をベースに検索してみると、同じことを問題にしているIssueが見つかりました。
一安心です。
対策
reactのv18から修正されているようなので、シンプルな解決方法はnpmライブラリもNextJsプロジェクトのどちらも最新Versionに上げるということでしたが、それは色々な兼ね合いでできません。
したがって、npmライブラリ側のバンドルでjsx-runtimeを含まないよう以下のように変更しました。これにより、ReactがJSX解釈に必要になるので、Componentファイルにimport React from 'react'も行いました。
{
"compilerOptions": {
,
"jsx": "react",
最後に
NextJsプロジェクトのtsconfig.jsonを見てみると、"jsx":"preserve"固定になっていたので、この辺がちゃんと考慮されているようでした。
補足
NextJsプロジェクト側でreact/jsx-runtimeとreact/jsx-runtime.jsを紐づけるように解決するという方法もありますが、npmライブラリ導入により、本体プロジェクト側に設定関連の修正を与えたくなかったので、採用しませんでした。