.gitignore for React with Vite

node_modules/ coverage/ .env dist/ dist-ssr/ *.local

A React app built with Vite needs node_modules/, the dist/ build (and dist-ssr/ for server rendering), coverage/, and env files: *.local for Vite’s local overrides, plus .env. React itself writes no files, so these come from the tool’s Node.js and Vite templates, which typing react picks together: 43 lines once the two duplicates are dropped. The answer above is their key lines.

What the blocks ignore

  • Node.js: node_modules/, the npm, Yarn and pnpm debug logs, caches such as .eslintcache and *.tsbuildinfo, coverage/, and .env, .env.local and .env.*.local.
  • Vite: dist/ and dist-ssr/, the production build; .vite/, for Vite’s dependency cache when it isn’t in its default home under node_modules/; and *.local.

In a scratch repository with this file, git check-ignore -v -n --no-index names the line that matched each path, or prints :: when none did:

.gitignore:53:dist/	dist/assets/index-abc.js
.gitignore:3:node_modules/	node_modules/.vite/deps/react.js
.gitignore:47:.env	.env
.gitignore:57:*.local	.env.local
::	.env.production
.gitignore:57:*.local	.env.production.local
::	package-lock.json

.env.local is reported against *.local on line 57, not the Node.js block’s .env.local on line 48: when several lines match, the last one decides.

Which env files to commit

Vite’s documentation marks only the .local files as ignored by Git: .env.local and .env.[mode].local hold values for one machine, which leaves .env, .env.development and .env.production as the shared ones. The Node.js template ignores .env anyway, which is the safer default. Either way, nothing secret belongs in a VITE_ variable: Vite inlines those into the client bundle, where anyone can read them. Commit package-lock.json (or your manager’s lockfile) too.

dist/ matches at any depth

Without a leading slash, dist/ also hides a source folder called dist:

.gitignore:53:dist/	src/dist/format.ts

Anchor it as /dist/ in its place and only the build goes:

.gitignore:53:/dist/	dist/assets/index-abc.js
::	src/dist/format.ts

A directory line also limits ! lines: Git never looks inside an excluded directory, so after dist/ no !dist/... line can keep a file. Ignore /dist/* instead if you need one back, such as a _redirects file kept with !/dist/_redirects.

Already committed dist/?

.gitignore only affects untracked files. Untrack the build, keeping it on disk, and commit:

git rm -r --cached dist
git commit -m "Stop tracking the build"

Editor and OS files

create-vite writes editor lines such as .vscode/* and .idea into its own .gitignore. Pick the VS Code or JetBrains template here, or keep editor and OS files in a global ignore file:

git config --global core.excludesFile ~/.gitignore_global

Try it in the Gitignore Generator

In the file: Node.js, Vite

.gitignore

2 templates · 43 pattern lines · 2 duplicates dropped
# Node.js
# Dependencies installed by npm, Yarn, pnpm or Bun
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
.pnpm-debug.log*
lerna-debug.log*
# Diagnostic reports Node writes to the working directory when it crashes
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
*.pid
*.pid.lock
*.seed
lib-cov/
# Coverage reports from c8, nyc or Jest
coverage/
*.lcov
.nyc_output/
.cache/
.parcel-cache/
.grunt/
bower_components/
jspm_packages/
web_modules/
# TypeScript's incremental build cache
*.tsbuildinfo
.eslintcache
.stylelintcache
# Tarballs written by npm pack
*.tgz
.node_repl_history
# Yarn's cache and install state; the five lines below re-include what has to be committed
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
# Yarn's Plug'n'Play files
.pnp.*
.npm/
.lock-waf*
# Native addons built by node-gyp
build/Release/
# Local environment files; commit .env.example instead
.env
.env.local
.env.*.local

# Vite
# The production build
dist/
dist-ssr/
# Vite's dependency pre-bundle cache
.vite/
*.local
  • ✗Ignored by "*.local" (Vite).

Lines are applied top to bottom, and the last one that matches wins — which is why a line of your own can overrule a template. This one was read as a file.

Runs in your browser. Nothing you enter is sent anywhere.