Vite 内など ES Module 指定のフォルダ内で __dirname を通すメモ

Vite 内など ES Module 指定のフォルダ内で __dirname を通すメモです。

背景

Vite で生成したフォルダなど ES Module 指定になっています。

{
  "name": "vite-project",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "node server.js & vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "devDependencies": {
    "typescript": "^5.2.2",
    "vite": "^5.2.0"
  },
  "dependencies": {
    "express": "^4.19.2"
  }
}

package.json で "type": "module" な指定をしていると、そうなります。

さてこういった ES Module 指定のフォルダ内で Express での app.use(express.static(__dirname + '/public')); を使ったフォルダ指定など __dirname を使いたいときにエラーになるので、使えるようにしたいことがあります。

console.log(__dirname);

こういう記述があるとして、実行すると

file:///workspaces/vite-server-test/vite-project/app.js:1
console.log(__dirname);
            ^

ReferenceError: __dirname is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '/workspaces/vite-server-test/vite-project/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
    at file:///workspaces/vite-server-test/vite-project/app.js:1:13
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async loadESM (node:internal/process/esm_loader:28:7)
    at async handleMainPromise (node:internal/modules/run_main:113:12)

エラーの内容はこんな感じになります。

__dirname を使えるようにする

というわけで __dirname を通しましょう。

こちらの記事を参考にしつつ、このように修正します。

import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

console.log(__dirname);

このように修正すると

/workspaces/vite-server-test/vite-project (main) $ node app.js 
/workspaces/vite-server-test/vite-project

と同じように動作するようになりました!

実際、今回のエラーで調べてみると、以下のようにみなさんハマっているようです。

この機会にうまく解消できてよかったです。