しばらく触っていなかった Next.js のプロジェクトを久しぶりに開いて、1行だけ直してデプロイしようとしたら、ビルドが落ちました。
自分が触った場所とはまったく関係ないファイルでエラーが出ていて、一瞬「壊した?」と焦ったやつです。同じところで詰まる人がいそうなので残しておきます。
出たエラー
Failed to type check.
./components/calculators/YamlJsonConverter.tsx:4:28
Type error: Could not find a declaration file for module 'js-yaml'.
'node_modules/js-yaml/dist/js-yaml.mjs' implicitly has an 'any' type.
Try `npm i --save-dev @types/js-yaml` if it exists or
add a new declaration (.d.ts) file containing `declare module 'js-yaml';`
エラーの意味(TypeScriptに慣れていない人向け)
まず前提から。TypeScript は「この関数は何を受け取って何を返すか」を知りたがります。 その情報が書いてあるのが 型定義ファイル(.d.ts)です。
ライブラリには2種類あります。
| 種類 | 型定義の場所 |
|---|---|
| TypeScriptで書かれたライブラリ | 本体に最初から入っている |
| JavaScriptで書かれたライブラリ | 別パッケージ @types/xxx に分かれている |
js-yaml は後者です。なので本体の js-yaml と、型定義の @types/js-yaml の2つが必要になります。
エラーは「js-yaml の型定義が見つからないので、中身が全部 any(何でもあり)になってしまう。それは許可されていない」と言っています。
素直に従うと、たぶん解決しません
エラーメッセージには親切に対処法が書いてあります。
Try `npm i --save-dev @types/js-yaml` if it exists
私も最初これを打とうとしました。でもその前に package.json を見たら、もう書いてあったんです。
grep -n "js-yaml" package.json
13: "@types/js-yaml": "^4.0.9",
15: "js-yaml": "^5.4.1",
両方ちゃんと書いてある。 じゃあなんで見つからないのか。
犯人:node_modules に実際には入っていなかった
package.json は「入れる予定のリスト」であって、「いま入っているもの」ではありません。ここが分かれていることを、私はこのとき初めて実感しました。
実際に入っているものは node_modules/ の中を見れば分かります。
ls node_modules/@types/
debug estree estree-jsx hast json-schema json5
mdast ms node qrcode react react-dom unist
js-yaml が無い。
リストには載っているのに、棚には並んでいない状態でした。
直し方
npm install
これだけです。package.json を見て、足りないものを入れ直してくれます。
ls node_modules/@types/ | grep -i yaml
# js-yaml ← 入った
npm run build
# ✓ ビルド成功
なぜこうなるのか
node_modules と package.json がズレる原因はいくつかあります。
-
npm installの途中で止まった(Ctrl+C、ネットワーク切断、PCのスリープなど) - 別のブランチで作業していて戻ってきた(ブランチごとに依存が違う場合)
-
git pullでpackage.jsonだけ更新された(node_modulesはGitに入らないので追従しない) - ディスクの空き不足で書き込みに失敗していた
★私の場合は最後に触ったのが数日前で、そのときの npm install が完走していなかったのが原因でした。エラーが出ていたのかもしれませんが、その場では気づかずに終わっていたようです。
そして厄介なのが、開発サーバー(npm run dev)では気づかないことがある点です。今回のエラーは型チェックで出るもので、next dev は型チェックを止めないので、ビルドして初めて落ちました。
教訓:しばらく触っていないプロジェクトは、まずビルドを通す
今回いちばん危なかったのは、「自分が直した1行のせいだ」と思い込みかけたことです。実際にはまったく無関係な、前から壊れていた状態でした。
なので、久しぶりに開いたプロジェクトでは、何かを直す前に一度ビルドを通すのがおすすめです。
npm install && npm run build
これで通ってから作業を始めれば、次にビルドが落ちたときに「さっき自分が触ったところが原因」と断定できます。切り分けが一気にラクになります。
私は ShibaHub という計算ツールのサイトを個人で運営していて、数日〜数週間ぶりに触ることがよくあります。この順番を守るだけで、無駄に焦る時間がかなり減りました。
まとめ
-
package.jsonは「入れる予定」、node_modulesは「いま入っているもの」。ズレる - エラーメッセージが
npm iを勧めてきても、まずpackage.jsonに既にあるか確認する - あるのに動かないなら
ls node_modules/@types/で実物を見る - 直し方は
npm installだけ - 久しぶりのプロジェクトは、触る前にビルドを通しておく