Configuring Vitest in a DevContainer
Vitest gives fast unit-test feedback, and running it inside the devcontainer keeps tests on the same toolchain as the build. This page configures Vitest in a container — resolving the same TypeScript path aliases, watching efficiently, and reusing the cached dependency store.
Prerequisites
You need a Node/TypeScript devcontainer with Vitest.
- A Node Feature pinned and the package manager set.
- Vitest as a dev dependency.
- tsconfig path aliases mirrored in the Vitest config.
Step-by-Step Implementation
- Install Vitest and resolve tsconfig path aliases.
// vitest.config.ts
import { defineConfig } from 'vitest/config';
import tsconfigPaths from 'vite-tsconfig-paths';
export default defineConfig({ plugins: [tsconfigPaths()] });
- Run tests inside the container.
corepack pnpm vitest run
- Use watch mode for feedback (polling if file events are flaky on a mount).
pnpm vitest --watch
- Verify aliases resolve and tests pass.
pnpm vitest run # @app/* imports resolve like the build
Common Pitfalls
Vitest issues are unresolved aliases or flaky watch on a bind mount.
| Symptom | Root Cause | Remediation |
|---|---|---|
| @app/* fails only in tests | Vitest doesn't read tsconfig paths | Add vite-tsconfig-paths plugin |
| Watch mode misses changes | Bind-mount file events flaky | Enable polling in watch |
| Tests differ from CI | Unpinned Vitest/runtime | Pin Vitest and the Node version |
| Slow installs before tests | Store not cached | Cache the pnpm/npm store on a volume |
Conclusion
Run Vitest inside the container so tests use the same toolchain as the build, resolve TypeScript path aliases with the tsconfig-paths plugin so imports match, and enable polling if a bind mount makes file events flaky. Fast, faithful test feedback in the environment developers actually use.
FAQ
Why do my Vitest imports fail on path aliases?
Because Vitest doesn't automatically read tsconfig.json paths. Add the vite-tsconfig-paths plugin to vitest.config.ts so the test runner resolves @app/* the same way the type-checker and build do, and the imports work in tests.
Why does watch mode miss my changes in a container? Native file-system events can be unreliable across a bind mount. Enable polling in Vitest's watch configuration so it detects changes by polling the filesystem, which is more reliable in a mounted workspace at the cost of slightly more CPU.
How do I keep Vitest results consistent with CI?
Pin Vitest as a dev dependency and pin the Node version via the Feature, so the container and CI run identical versions. Run tests inside the container in both places (locally and via devcontainer exec in CI) for the same toolchain.
Related
- Up to Node.js & TypeScript Workspace Configuration — the Node overview.
- Configuring TypeScript Path Aliases in a DevContainer — the aliases Vitest must resolve.
- Using pnpm Workspaces in a DevContainer — the cached store behind fast installs.