Path & Environment Variables
The path module
Working with file paths is tricky because the separator character is / on Mac/Linux and \ on Windows. The built-in path module handles this for you automatically.
import path from 'path'
const filePath = path.join('folder', 'subfolder', 'file.txt')
console.log(filePath) // 'folder/subfolder/file.txt' on Mac/Linux
Common path methods
import path from 'path'
const full = '/Users/alice/projects/app/src/index.js'
console.log(path.basename(full)) // 'index.js'
console.log(path.dirname(full)) // '/Users/alice/projects/app/src'
console.log(path.extname(full)) // '.js'
console.log(path.join('src', 'utils.js')) // 'src/utils.js'
console.log(path.resolve('src', 'utils.js')) // absolute path based on cwd
path.join builds a path from parts. path.resolve does the same but always returns an absolute path starting from the current working directory.
__dirname with ES Modules
In CommonJS, __dirname gives you the directory of the current file. In ES Modules it does not exist, but you can recreate it:
import { fileURLToPath } from 'url'
import path from 'path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
console.log(__dirname) // directory of the current file
Environment variables
Environment variables let you pass configuration to your app without hardcoding it in the source code. This is how you keep secrets like API keys and database passwords out of your code.
Node.js exposes them through process.env.
Reading environment variables
// index.js
const port = process.env.PORT
console.log('Running on port:', port)
Set them when you start the app:
PORT=4000 node index.js
Output:
Running on port: 4000
Default values
Use ?? to provide a fallback when a variable is not set:
const port = process.env.PORT ?? 3000
const env = process.env.NODE_ENV ?? 'development'
.env files
In real projects, use a .env file to store all your environment variables. Install the dotenv package to load them:
npm install dotenv
Create a .env file in the root of your project:
PORT=4000
DATABASE_URL=postgres://localhost/mydb
SECRET_KEY=supersecret
Load it at the top of your entry file:
import 'dotenv/config'
console.log(process.env.PORT) // '4000'
console.log(process.env.DATABASE_URL) // 'postgres://localhost/mydb'
Important: Add .env to your .gitignore file so you never commit secrets to version control.
If you are using VITE, it automatically loads .env files without needing dotenv. Just prefix your variables with VITE_ to make them available in your client-side code:
VITE_API_URL=https://api.example.com
Then you can access it in your JavaScript:
console.log(import.meta.env.VITE_API_URL) // 'https://api.example.com'