JavaScript: Error [ERR_MODULE_NOT_FOUND]: Cannot find package ‘readline-sync’ imported from /Users〜 が出た時の対応(備忘録)

JavaScript
harshaharsによるPixabayからの画像

JavaScriptの環境についてのエントリが続きます。

Warning: To load an ES module, set “type”: “module” in the package.json or use the .mjs extension. への対応(備忘録)

前回のエントリで複数フォルダの複数ファイルに跨がるscriptをimport, exportして実行できる様にできた。

その後も、プロゲート上で実行したscriptファイルを拡張子を付けるなど修正し、自分のMac上に保存して実行させていた。
そんな現在のフォルダ構成は下記の通り。

.
├── class
│   ├── animal.js
│   └── dog.js
├── data
│   └── dogData.js
├── package-lock.json
├── package.json
└── script.js

2 directories, 6 files

しばらく上手く行っていたが、外部のパッケージをimportするscriptファイルにおいて下記エラーが出た。

% node script.js 
node:internal/errors:464
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'readline-sync' imported from /Users/(ユーザー名以降のパス)/files/data/dogData.js
    at new NodeError (node:internal/errors:371:5)
    at packageResolve (node:internal/modules/esm/resolve:884:9)
    at moduleResolve (node:internal/modules/esm/resolve:929:18)
    at defaultResolve (node:internal/modules/esm/resolve:1044:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:422:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:222:40)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

エラーメッセージによると、パッケージ “readline-sync”が見つからないとの事。

まずは”Error [ERR_MODULE_NOT_FOUND]: Cannot find package ‘readline-sync’ imported from”で検索、
Error: Cannot find module ‘readline-sync’ : Node.jsでアドバイスされている通り
“npm install –save readline-sync”
を実行。

パッケージ “readline-sync”が私のMac上にないからインストール、と言う事だろう。
Pythonでも必要なモジュールはインストールする必要があるのでこれは分かる。

% npm install --save readline-sync             

added 1 package, and audited 2 packages in 2s

found 0 vulnerabilities

インストール後、ファイルを実行すると”Cannot find package ‘readline-sync”は無くなったが、script.jsを実行するとやはりエラーメッセージが出る。

% node script.js                  
node:internal/errors:464
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/Users/ユーザー名/~/files/class/dog' imported from /Users/ユーザー名/~/files/data/dogData.js
    at new NodeError (node:internal/errors:371:5)
    at finalizeResolution (node:internal/modules/esm/resolve:416:11)
    at moduleResolve (node:internal/modules/esm/resolve:932:10)
    at defaultResolve (node:internal/modules/esm/resolve:1044:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:422:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:222:40)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

npm installも実行してみるも、同じエラーが出た。

% npm install

up to date, audited 2 packages in 762ms

found 0 vulnerabilities

現在のツリーは下記の通り。
フォルダ”node_modules”が出来ているのが分かる。

% tree
.
├── class
│   ├── animal.js
│   └── dog.js
├── data
│   └── dogData.js
├── node_modules
│   └── readline-sync
│       ├── LICENSE
│       ├── README-Deprecated.md
│       ├── README.md
│       ├── lib
│       │   ├── encrypt.js
│       │   ├── read.cs.js
│       │   ├── read.ps1
│       │   ├── read.sh
│       │   └── readline-sync.js
│       └── package.json
├── package-lock.json
├── package.json
└── script.js

5 directories, 15 files

色々見ていて、”dogData.js”ファイル内で下記の行を見つける。

import readlineSync from "readline-sync";

フォルダ内ファイルのimport, exportにおいては拡張子.jsを付けていたんだから、パッケージも同じだろう。

と言う事で”readline-sync”の部分に.jsの拡張子を付けて実行するとエラーメッセージが変わった。

% node script.js
node:internal/errors:464
    ErrorCaptureStackTrace(err);
    ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'readline-sync.js' imported from /Users/ShujiKatoMBPro/Dropbox/0_Udacity/0_Full_Stack_Web_Developer/Playground/JS_Playground/Progate_sample/files/data/dogData.js
    at new NodeError (node:internal/errors:371:5)
    at packageResolve (node:internal/modules/esm/resolve:884:9)
    at moduleResolve (node:internal/modules/esm/resolve:929:18)
    at defaultResolve (node:internal/modules/esm/resolve:1044:11)
    at ESMLoader.resolve (node:internal/modules/esm/loader:422:30)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:222:40)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

そうか、ただ拡張子を変えただけでは読み込めないよね。
と、インポートの一行を下記の相対パスに修正した上でscript.jsを実行したら実行出来た。

import readlineSync from "../node_modules/readline-sync/lib/readline-sync.js";

要は、”readline-sync”に限らず外部パッケージが無いよ、と言うエラーでした。

プロゲート上ではサーバ内にパッケージが保存されているから
ただ
“import readlineSync from “readline-sync”;
とするだけでインポートして使用出来たのだろう。

JavaScriptをnodeで実行し、外部のパッケージを利用する際には、そのパッケージを自分がscriptファイルを実行しているディレクトリにある”node_modules”フォルダ内にインストール、相対パスを設定する必要が有るのだろう。
多分JS/nodeをお使いの方には当たり前なのでしょうが、今理解しました。

で、そのパッケージを管理するのがpackage.jsonファイル。
現時点のpackage.jsonファイルは下記の通り。
今回インストールした”readline-sync”が有るのが分かる。

{
  "name": "files",
  "version": "1.0.0",
  "description": "",
  "main": "script.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "readline-sync": "^1.4.10"
  }
}

Pythonではpip等でインストールしたモジュールはパス無しのimport文でインポートできるが、JavaScriptにおいては都度パッケージの場所を指定する必要がある、と言うのが現在の理解。

コメント

タイトルとURLをコピーしました