2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Node.jsのreadFileは起動場所で読むファイルが変わる:import.meta.urlとの違いを実測

2
Posted at

同じNode.jsスクリプトなのに、起動する場所を変えただけで別のファイルを読んでしまうことがあります。fs.readFile('./message.txt')の基準は、スクリプトの保存場所ではなくプロセスの作業ディレクトリです。

2026年10月26日、macOS 27.0.1・Node.js v24.22.1で実測しました。ここではローカルのES Modules(.mjs)を扱います。Windows、CommonJS、バンドラー経由の実行は試していません。

同じ名前のファイルを二つ用意する

新しい練習フォルダに、次の構成を作ります。既存プロジェクトへ上書きせず、空の場所で試してください。

practice/
├── message.txt       内容は ROOT
└── app/
    ├── message.txt   内容は APP
    └── read.mjs

read.mjsは次のコードです。ファイルの読み込み方法だけを二通りに分けます。

import { readFile } from 'node:fs/promises';
console.log('relative:', (await readFile('./message.txt', 'utf8')).trim());
console.log('module:', (await readFile(new URL('./message.txt', import.meta.url), 'utf8')).trim());

new URL('./message.txt', import.meta.url)は、このモジュールのURLを基準に隣のファイルを指定します。今回のNode.jsのreadFileはfile URLのオブジェクトを受け取れるので、文字列のパスへ変換せず渡しています。

appの中から起動した結果

appディレクトリを作業場所にして実行します。

node read.mjs

実測した標準出力です。終了コードは0でした。

relative: APP
module: APP

作業場所とモジュールの場所が同じなので、どちらもapp/message.txtを読みます。この実行だけでは基準の違いは見えません。

親のpracticeから起動すると変わる

今度はpracticeディレクトリを作業場所にして、同じファイルを実行します。

node app/read.mjs

コードもファイルの中身も変えていません。実測結果は次のとおりで、終了コードは0でした。

relative: ROOT
module: APP

相対パス文字列で渡した方はpractice/message.txtを読み、モジュールのURLを基準にした方はapp/message.txtを読みました。誤ったファイルでも読み込み自体が成功すると、ENOENTのようなエラーは出ません。

親のファイルがなければENOENTになる

次に、親のpractice/message.txtだけを取り除いて同じ実行を試しました。app/message.txtは残しています。標準出力は空で、標準エラー出力には次のメッセージがあり、終了コードは1でした。

Error: ENOENT: no such file or directory, open './message.txt'

上のread.mjsでは一つ目のawaitが失敗するため、二つ目の読み込みまでは進んでいません。この結果を「URLで指定しても失敗した」とは読めません。

どちらを基準にするかを用途で決める

  • スクリプトに同梱したテンプレートや固定データを読むなら、モジュールを基準にする設計が候補です。
  • 利用者が作業中のフォルダに置いた入力を読むなら、作業ディレクトリを基準にする設計が候補です。

相対パスをすべてURLへ置き換えればよい、という話ではありません。起動場所を変えたときも同梱データを読みたいのか、起動した場所の入力を読みたいのかを決めます。

Node.js公式:ファイルパスでは文字列の相対パスを作業ディレクトリ基準で扱うこと、Node.js公式:ES Modulesではimport.meta.urlを使う読み込み例を確認できます。この記事の結果は上記の実測環境に限り、ブラウザのfetchやimport指定子全般へは拡張しません。


未経験者向けの体験版を公開しています

※ 中上級者には易しすぎる内容なので、初心者の知り合いへの紹介や社内研修の参考としてどうぞ。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?