Node.js configuration extends the ESNext base configuration with Node.js-specific environment settings and rules. It provides safety checks and best practices tailored for server-side JavaScript development, focusing on Node.js API usage patterns and common pitfalls.
Node.js-specific ESLint configuration that extends ESNext with server-side JavaScript rules.
/**
* Node.js ESLint configuration
* Accessible as: "node" or "recommended/node"
*/
env:
node: true # Enable Node.js global variables and scoping
extends: esnext # Inherit all ESNext rules and configuration
rules:
no-path-concat: 2 # Error: disallow string concatenation with __dirname/__filename
no-process-exit: 2 # Error: disallow the use of process.exit()
no-sync: 1 # Warning: disallow synchronous methods
import/no-nodejs-modules: 0 # Disabled: allow importing Node.js built-in modulesEnvironment Settings:
node: true: Enables Node.js global variables and Node.js scoping including:
global, process, Buffer, setImmediate, clearImmediate__dirname, __filenamemodule, exports, requireExtended Configuration:
esnext: Inherits all rules from eslint-config-esnext providing modern JavaScript/ES6+ linting foundationRules that address common Node.js development issues and promote best practices.
/**
* Node.js-specific linting rules
*/
rules: {
/**
* no-path-concat: Disallow string concatenation with __dirname and __filename
* Level: Error (2)
* Prevents unsafe path construction that may fail on different operating systems
*/
"no-path-concat": "error",
/**
* no-process-exit: Disallow the use of process.exit()
* Level: Error (2)
* Prevents abrupt process termination that bypasses cleanup and error handling
*/
"no-process-exit": "error",
/**
* no-sync: Disallow synchronous methods
* Level: Warning (1)
* Warns against blocking the event loop with synchronous operations
*/
"no-sync": "warn",
/**
* import/no-nodejs-modules: Allow importing Node.js built-in modules
* Level: Disabled (0) - overrides ESNext configuration
* Permits importing Node.js core modules like 'fs', 'path', 'http', etc.
*/
"import/no-nodejs-modules": "off"
}# .eslintrc.yaml
extends:
- node
# Optional project-specific rules
rules:
no-console: warn# .eslintrc.yaml
extends:
- node
rules:
# Stricter for production servers
no-console: error
no-sync: error
# Allow process.exit in CLI scripts
no-process-exit: off
env:
# Add additional environments
jest: true
overrides:
# Allow console in development/test files
- files: ['**/*.test.js', '**/*.spec.js', 'scripts/**/*.js']
rules:
no-console: off# .eslintrc.yaml
extends:
- node
rules:
# Common Express patterns
no-unused-vars: [error, { argsIgnorePattern: '^(req|res|next)$' }]
# Allow callback pattern
consistent-return: off# .eslintrc.yaml
extends:
- node
rules:
# CLI tools often need these
no-console: off
no-process-exit: off
no-sync: offThis rule prevents unsafe path construction that may fail across different operating systems.
// ❌ Error: String concatenation with __dirname
const configPath = __dirname + '/config.json';
const logPath = __dirname + '/../logs/app.log';
const templatePath = __filename + '.template';
// ✅ Correct: Use path.join()
const path = require('path');
const configPath = path.join(__dirname, 'config.json');
const logPath = path.join(__dirname, '..', 'logs', 'app.log');
const templatePath = path.join(path.dirname(__filename), path.basename(__filename) + '.template');
// ✅ Also correct: Use path.resolve() for absolute paths
const configPath = path.resolve(__dirname, 'config.json');This rule prevents abrupt process termination that bypasses proper cleanup and error handling.
// ❌ Error: Direct process.exit() call
if (error) {
console.error('Fatal error:', error);
process.exit(1);
}
if (!config.apiKey) {
console.error('API key required');
process.exit(1);
}
// ✅ Correct: Throw error for proper error handling
if (error) {
throw new Error(`Fatal error: ${error.message}`);
}
if (!config.apiKey) {
throw new Error('API key required');
}
// ✅ Also correct: Set exit code and let process end naturally
if (error) {
console.error('Fatal error:', error);
process.exitCode = 1;
return; // or throw error in async context
}
// ✅ Correct in CLI context: Use proper shutdown
async function shutdown(code = 0) {
await cleanup();
process.exit(code);
}This rule warns against synchronous operations that block the Node.js event loop.
// ⚠️ Warning: Synchronous file operation
const fs = require('fs');
const data = fs.readFileSync('data.txt', 'utf8');
const files = fs.readdirSync('./uploads');
const stats = fs.statSync('package.json');
// ✅ Better: Use async versions with async/await
const fs = require('fs').promises;
async function loadData() {
const data = await fs.readFile('data.txt', 'utf8');
const files = await fs.readdir('./uploads');
const stats = await fs.stat('package.json');
return { data, files, stats };
}
// ✅ Also correct: Use callback versions
const fs = require('fs');
fs.readFile('data.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// ✅ Acceptable: Sync operations in startup/initialization code
// (where blocking is acceptable)
const config = JSON.parse(fs.readFileSync('config.json', 'utf8'));This rule is disabled in Node.js config to allow importing Node.js built-in modules.
// ✅ Allowed in Node.js config (disabled rule)
import fs from 'fs';
import path from 'path';
import http from 'http';
import crypto from 'crypto';
import { promisify } from 'util';
// CommonJS also allowed
const fs = require('fs');
const path = require('path');The Node.js configuration enables these global variables and features:
// ✅ Available globals (no-undef won't flag these)
console.log(global); // Global namespace object
console.log(process); // Process object
console.log(Buffer); // Buffer constructor
console.log(__dirname); // Current directory path
console.log(__filename); // Current file path
// Timer functions
setImmediate(callback);
clearImmediate(immediateId);// ✅ CommonJS globals available
console.log(module); // Current module object
console.log(exports); // Module exports object
console.log(require); // Module require function
// Module properties and methods
console.log(module.filename);
console.log(module.id);
console.log(require.resolve('./module'));// ✅ Proper async error handling
async function processFile(filename) {
try {
const data = await fs.readFile(filename, 'utf8');
return JSON.parse(data);
} catch (error) {
// Log and re-throw or handle appropriately
console.error(`Failed to process ${filename}:`, error.message);
throw error;
}
}
// ✅ Callback error handling
function processFile(filename, callback) {
fs.readFile(filename, 'utf8', (err, data) => {
if (err) {
return callback(err);
}
try {
const result = JSON.parse(data);
callback(null, result);
} catch (parseError) {
callback(parseError);
}
});
}const path = require('path');
// ✅ Cross-platform path operations
const configDir = path.join(__dirname, 'config');
const logFile = path.resolve(process.cwd(), 'logs', 'app.log');
const extension = path.extname(__filename);
const basename = path.basename(__filename, '.js');Inherited from ESNext:
babel-eslint: ^10.0.1 - Parser for modern JavaScript syntaxeslint: ^6.8.0 - ESLint coreeslint-plugin-babel: ^5.2.1 - Babel-specific ESLint ruleseslint-plugin-import: ^2.14.0 - Import/export validation rulesAdditional Dependencies:
eslint-config-esnext: ^4.1.0 - Base ESNext configurationPeer Dependencies:
eslint: ^6.0.0 - Required ESLint version for consuming projectsnpm install --save-dev eslint-config-recommended# .eslintrc.yaml
extends:
- recommended/nodenpm install --save-dev eslint-config-node# .eslintrc.yaml
extends:
- node