EngineeringEnvironment VariablesNode.jsGitESLint

Front-End Config: Env, Node, Git, ESLint, and TypeScript

Set up .env files, Node versions, Git ignores, ESLint flat config, Prettier, and TypeScript with clear responsibilities, safe secret handling, and a repeatable workflow.

·Updated ·14 min read·计算中...

Front-end configuration files are easier to maintain when each one has a narrow job: .env supplies environment-specific values, .nvmrc coordinates Node versions, .gitignore excludes files Git should not start tracking, and ESLint reports code problems. Do not add Babel, Prettier, or another config because an old tutorial said every project needs one—add it when the build or team workflow needs it.

.env: configuration values, not a secret vault

DATABASE_URL=postgresql://localhost:5432/app
API_BASE_URL=http://localhost:3000

Node can load dotenv-style files into process.env; modern Node also supports CLI options such as --env-file. The syntax is convenient, but it does not make a value private.

node --env-file=.env server.js

Keep these boundaries clear:

  • Do not commit real production secrets in .env files.
  • Commit .env.example with variable names and safe placeholder values.
  • Treat every value shipped in a browser bundle as public.
  • If a secret reached Git history, rotate it immediately; adding the file to .gitignore does not revoke it.
  • Let the deployment platform or a secret manager inject production values.
  • Validate required environment variables at startup, not halfway through a user request.
const siteUrl = process.env.NEXT_PUBLIC_SITE_URL

if (!siteUrl) {
  throw new Error("Missing NEXT_PUBLIC_SITE_URL")
}

Frameworks define their own file precedence and client-exposure conventions. In Next.js, a NEXT_PUBLIC_ prefix exposes a value to browser code, so it must never contain a database password or server token.

.nvmrc and engines: keep Node versions aligned

An .nvmrc at the project root can contain a version such as:

20

Then local users of nvm can run:

nvm install
nvm use

For a more explicit compatibility statement, include an engines range in package.json:

{
  "engines": {
    "node": ">=20 <23"
  }
}

.nvmrc helps local nvm users; engines communicates supported versions to package managers and hosting platforms. Your CI workflow and Docker image should still use an explicit compatible version—do not assume they read .nvmrc automatically.

.gitignore: prevents new tracking, not history cleanup

A typical Node or Next.js project starts with rules like these:

node_modules/
.next/
dist/
coverage/
*.log
.DS_Store

.env
.env.*
!.env.example

Useful rules to remember:

  • /dist only targets a root-level dist; dist/ can match corresponding directories.
  • ** can match across nested directories.
  • ! re-includes a path, although a fully ignored parent directory may require an additional rule.
  • Shared rules belong in .gitignore; personal machine-wide rules belong in Git's global exclude file.

An already tracked file is not removed just because you add it to .gitignore. Review the impact first, then remove only the index entry if that is truly intended:

git rm --cached path/to/file

To discover which ignore rule matches a path:

git check-ignore -v path/to/file

That command is a diagnostic tool; it does not undo a leaked secret or rewrite repository history. Follow a deliberate Git workflow before making tracked files disappear from a shared repository.

Babel: confirm that you need it

Modern frameworks such as Next.js and Vite already provide a transform pipeline. If you have no custom transform, unusual syntax, or library-build requirement, adding a .babelrc may create duplicate work or bypass framework optimizations.

When a project really needs Babel, choose the configuration scope intentionally:

  • babel.config.* is project-wide and can suit monorepos.
  • .babelrc.* is resolved relative to packages and files.
  • A babel field in package.json suits very small configurations.

Keep the configuration minimal and explain why it exists in the repository documentation.

ESLint: use flat config for new work

ESLint's current configuration format is flat config: an eslint.config.js, .mjs, or .cjs file at the project root that exports an array of configuration objects.

// eslint.config.mjs
import js from "@eslint/js"
import { defineConfig } from "eslint/config"

export default defineConfig([
  js.configs.recommended,
  {
    files: ["**/*.{js,mjs,cjs}"],
    rules: {
      "prefer-const": "error",
      "no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
    },
  },
  {
    ignores: ["dist/**", ".next/**", "coverage/**"],
  },
])

For React, TypeScript, or Next.js, start from the framework's current recommended configuration rather than copying this plain-JavaScript example blindly. In flat config, ignore patterns belong in a configuration object; old .eslintignore behavior does not automatically carry over. See the official ESLint configuration documentation when migrating an older project.

Let TypeScript, ESLint, and Prettier do different jobs

Tool Primary responsibility
TypeScript Type checking
ESLint Error patterns, code quality, and framework rules
Prettier Formatting
EditorConfig Baseline indentation and line-ending behavior across editors

Avoid making ESLint and Prettier enforce the same formatting choices. It adds noise to review without improving the code. Use the editor to format consistently, then keep linting focused on correctness and project conventions.

A sensible repository baseline

project/
├── .env.example
├── .gitignore
├── .nvmrc
├── eslint.config.mjs
├── prettier.config.mjs
├── package.json
└── tsconfig.json

CI should run the checks the project actually depends on, typically in an order that gives quick feedback:

npm run lint
npm run typecheck
npm run format:check
npm test
npm run build

Use the same assumptions locally and in CI. A project that passes only on one contributor's machine is missing configuration, not merely documentation.

Where to go next

For .env file parsing and the --env-file option, see the official Node.js environment-variable documentation. The goal is not a large config folder; it is a repository that behaves predictably for every contributor.

Subscribe to FreeMac

Weekly picks: free Mac software reviews, trusted source updates, alternatives, and low-friction guides.