Fine‑Tune ESLint’s no‑console Rule for Production vs Development
Stop accidental console statements in production by configuring ESLint’s no-console rule per environment. This guide shows how to set up overrides, run lint checks in CI, and balance convenience with safety.
11 Aug 2025, 01:09 UTC

The Problem
Adding console.log during development is a quick way to debug. If those statements slip into a production bundle they can leak sensitive data, clutter logs, or even expose internal state to end users. The simplest way to guard against this is to treat the no-console rule as a hard error when the code is destined for production.
Thesis
ESLint’s no-console rule can be toggled per environment using the overrides field. By keeping a single .eslintrc.json that switches the rule based on an environment variable, developers can use console statements locally while ensuring that any remaining console calls are caught before deployment.
How Overrides Work
The overrides array allows you to apply different rule sets to files that match a glob pattern. Combined with the env key you can detect the current build environment. A common pattern is to expose an environment variable called ESLINT_ENV that is set to development or production by your build scripts.
Configuration Skeleton
{
"env": {
"browser": true,
"node": true
},
"extends": ["eslint:recommended"],
"overrides": [
{
"files": ["**/*.js"],
"env": {
"es6": true
},
"rules": {
"no-console": "off"
}
},
{
"files": ["**/*.js"],
"env": {
"es6": true
},
"rules": {
"no-console": "error"
},
"conditions": ["production"]
}
]
}
ESLint does not natively support a conditions key, but you can achieve the same effect by splitting the configuration into two files or by using a pre‑commit hook that sets the variable before running lint.
Practical Example
Below is a minimal project structure that demonstrates the approach:
src/app.js– contains aconsole.logfor debugging..eslintrc.dev.json–no-consoleset tooff..eslintrc.prod.json–no-consoleset toerror.scripts/lint.js– runs ESLint with the appropriate config based onESLINT_ENV.
src/app.js
function greet(name) {
console.log(`Greeting ${name}`); // Debug
return `Hello, ${name}!`;
}
module.exports = greet;
.eslintrc.dev.json
{
"extends": "eslint:recommended",
"rules": {
"no-console": "off"
}
}
.eslintrc.prod.json
{
"extends": "eslint:recommended",
"rules": {
"no-console": "error"
}
}
scripts/lint.js
const { execSync } = require('child_process');
const env = process.env.ESLINT_ENV || 'development';
const config = env === 'production' ? '.eslintrc.prod.json' : '.eslintrc.dev.json';
try {
execSync(`npx eslint -c ${config} src/**/*.js`, { stdio: 'inherit' });
console.log(`Lint passed in ${env} mode.`);
} catch (err) {
console.error(`Lint failed in ${env} mode.`);
process.exit(1);
}
Running ESLINT_ENV=development node scripts/lint.js will ignore the console.log, whereas ESLINT_ENV=production node scripts/lint.js will throw an ESLint error and exit with a non‑zero status.
CI Integration
In a CI pipeline you typically want to run the production configuration on the main or release branches. Below is an example GitHub Actions workflow that enforces the rule.
.github/workflows/lint.yml
name: Lint
on:
push:
branches: [ main, release/* ]
pull_request:
branches: [ main, release/* ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- name: Run ESLint in production mode
env:
ESLINT_ENV: production
run: node scripts/lint.js
The job will fail if any console.* call remains in the codebase when the branch is pushed to production branches.
Trade‑offs & Limitations
- Configuration Drift – Using two separate config files requires duplication of rule sets. If you add a new rule, you must remember to update both files.
- Environment Variable Management – The build environment must reliably set
ESLINT_ENV. A typo or missing variable will cause the wrong rule set to be applied. - Intentional Production Logging – If your production code legitimately uses
console.logfor structured logging, the rule will block it. In that case you might opt for a custom rule that allows specific methods or a whitelist. - Tooling Overhead – Adding a script to switch configs adds a small learning curve for new contributors.
Actionable Checklist
- Define
ESLINT_ENVin your local dev environment and CI scripts. - Create two ESLint config files or a single config with environment checks.
- Run
node scripts/lint.jslocally before committing. - Integrate the production lint step into your CI pipeline.
- Periodically review the config files to keep rule sets in sync.
By following this pattern you maintain a clean production codebase while retaining the convenience of console debugging during development.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.