タイトル: npm ERR! path ~\%RESOURCE_DIR%\package.json
SEOタイトル: npm ERR! path %RESOURCE_DIR%/package.json の原因と対処(IDE / cross-env)
| この記事の要点 |
|
このエラーの概要
npm スクリプト実行時に次のようなエラーが表示されます:
npm ERR! code ENOENT
npm ERR! syscall open
npm ERR! path C:\Users\xxx\~\%RESOURCE_DIR%\package.json
npm ERR! errno -4058
npm ERR! enoent ENOENT: no such file or directory, open 'C:\...\%RESOURCE_DIR%\package.json'
npm ERR! enoent This is related to npm not being able to find a file.
注目すべきは パスに %RESOURCE_DIR% がそのまま残っている点です。本来であれば実際のディレクトリ(例: C:\Users\xxx\workspace\myapp)に展開されているはずが、文字列のまま渡されていることを意味します。
原因 1: package.json の scripts に環境変数記法
もっとも多いのが、Windows 用の %VAR% を Linux / macOS で実行しているケース、またはその逆です:
{
"scripts": {
"build": "webpack --config %RESOURCE_DIR%/webpack.config.js",
"test": "NODE_ENV=test jest"
}
}
npm の scripts は OS のシェルでそのまま実行されます:
- Windows (
cmd.exe):%VAR%展開、$VARは文字列のまま - Linux / macOS (
sh):$VAR展開、%VAR%は文字列のまま
つまり、%RESOURCE_DIR% を Linux 系で動かしたり、%RESOURCE_DIR% が そもそも定義されていない と未展開のまま渡ります。
原因 2: IDE の Run Configuration
IntelliJ IDEA / WebStorm / Android Studio の「npm Run Configuration」で、Working directory や Arguments に %RESOURCE_DIR% のような IDE マクロを書いたが、対応するマクロが未定義 / 別 IDE のマクロ、というケース:
- Android Studio:
$ModuleFileDir$/$ProjectFileDir$等が正しい - VSCode:
${workspaceFolder}/${fileDirname} %RESOURCE_DIR%は Android Studio Profile / 一部プラグインのマクロで、別コンテキストでは未定義
対処 1: cross-env でクロスプラットフォーム化
OS による環境変数記法の違いを吸収する定番が cross-env です:
npm install --save-dev cross-env{
"scripts": {
"build:dev": "cross-env NODE_ENV=development webpack",
"build:prod": "cross-env NODE_ENV=production webpack",
"test": "cross-env NODE_ENV=test jest"
}
}
cross-env を介すと、NODE_ENV=... 記法が Windows でもそのまま動きます。
対処 2: パス系は Node スクリプト経由に
パスを動的に組み立てる場合は、シェル変数に頼らず Node でやるほうが安全:
// scripts/build.js
const path = require('path');
const { execSync } = require('child_process');
const resourceDir = path.resolve(__dirname, '..', 'resources');
process.env.RESOURCE_DIR = resourceDir;
execSync(`webpack --config ${resourceDir}/webpack.config.js`, {
stdio: 'inherit',
env: process.env,
});{
"scripts": {
"build": "node scripts/build.js"
}
}
対処 3: IDE の Run Configuration を見直す
- Run → Edit Configurations を開く
- npm の Run Configuration を選択
- Working directory を絶対パスまたは正しい IDE マクロ(
$ProjectFileDir$等)に変更 - Environment variables に
RESOURCE_DIR=...を必要なら設定 - Apply → Run
対処 4: シェル側で事前に export
CI / シェルスクリプト経由なら、npm 実行前に環境変数を出してしまう手もあります:
# Linux / macOS
export RESOURCE_DIR=$(pwd)/resources
npm run build
# Windows cmd
set RESOURCE_DIR=%CD%\resources
npm run build
# Windows PowerShell
$env:RESOURCE_DIR = "$PWD\resources"
npm run build
原因の確認コマンド
# package.json の scripts を確認
cat package.json | jq .scripts
# 現在の環境変数に RESOURCE_DIR があるか
echo $RESOURCE_DIR # Linux/Mac
echo %RESOURCE_DIR% # Windows cmd
$env:RESOURCE_DIR # PowerShell
# npm の verbose ログ
npm run build --loglevel verbose
# 実際にどのコマンドが走るか
npm run build --dry-run # 一部の npm version で
関連エラー
| エラー | 原因 |
|---|---|
'NODE_ENV' is not recognized | Windows で NODE_ENV=x 記法 → cross-env で解決 |
ENOENT: no such file or directory | パス未展開 / 存在しないパス指定 |
$VAR is not defined | Windows で $VAR 記法 → %VAR% または cross-env |
FAQ
Q: cross-env を導入したくない
A: scripts を全部 Node スクリプト経由(node scripts/xxx.js)にすれば cross-env なしで OS 差を吸収できます。Node の process.env はクロスプラットフォームです。
Q: モノレポで子パッケージから親の RESOURCE_DIR を参照したい
A: npm-run-all や turbo で親から子を呼ぶときに --scope 経由で渡す、もしくは process.env を Node で組み立てる方が確実です。
Q: なぜ %RESOURCE_DIR% がパスに混入する?
A: scripts 文字列内の未展開リテラルを npm がそのまま現在ディレクトリのサブパスとして解釈し、ENOENT に到達するためです。