|
| 1 | +# Nested Configuration |
| 2 | + |
| 3 | +Vite+ supports multiple `vite.config.ts` files in the same repository, so packages in a monorepo can have their own lint and format settings while sharing a baseline. |
| 4 | + |
| 5 | +`vp lint` and `vp fmt` resolve configuration from the **current working directory** (cwd), but with one subtle difference: |
| 6 | + |
| 7 | +- **`vp lint`** — cwd-only. Uses `<cwd>/vite.config.ts` if it exists. If not, falls back to Oxlint's built-in defaults — it does **not** walk up to find an ancestor config. |
| 8 | +- **`vp fmt`** — cwd walk-up. Walks up from cwd and uses the first `vite.config.ts` it finds. If none is found anywhere up to the filesystem root, falls back to Oxfmt defaults. |
| 9 | + |
| 10 | +In both cases, the selected config applies to every path in the run. |
| 11 | + |
| 12 | +If you only need to exclude files or folders, use [`lint.ignorePatterns`](/config/lint) or [`fmt.ignorePatterns`](/config/fmt) instead. |
| 13 | + |
| 14 | +## How it works |
| 15 | + |
| 16 | +Given the following structure: |
| 17 | + |
| 18 | +``` |
| 19 | +my-project/ |
| 20 | +├── vite.config.ts |
| 21 | +├── src/ |
| 22 | +│ └── index.ts |
| 23 | +├── package1/ |
| 24 | +│ ├── vite.config.ts |
| 25 | +│ └── src/index.ts |
| 26 | +└── package2/ |
| 27 | + └── src/index.ts |
| 28 | +``` |
| 29 | + |
| 30 | +`vp lint`: |
| 31 | + |
| 32 | +- From `my-project/` → uses `my-project/vite.config.ts` for every file (including files under `package1/` and `package2/`). |
| 33 | +- From `my-project/package1/` → uses `my-project/package1/vite.config.ts`. |
| 34 | +- From `my-project/package2/` → no local `vite.config.ts`, so Oxlint's built-in defaults are used. |
| 35 | +- From `my-project/package1/src/` → no local `vite.config.ts`, so Oxlint's built-in defaults are used even though `package1/vite.config.ts` exists one level up. |
| 36 | + |
| 37 | +`vp fmt`: |
| 38 | + |
| 39 | +- From `my-project/` → uses `my-project/vite.config.ts`. |
| 40 | +- From `my-project/package1/` → uses `my-project/package1/vite.config.ts`. |
| 41 | +- From `my-project/package2/` → walks up past `package2/` and uses `my-project/vite.config.ts`. |
| 42 | +- From `my-project/package1/src/` → walks up past `src/` and uses `my-project/package1/vite.config.ts`. |
| 43 | + |
| 44 | +If your monorepo needs different settings per package, run `vp lint` / `vp fmt` from each package directory (for example, via a `vp run -r lint` task), or pin a specific config with `-c`. |
| 45 | + |
| 46 | +## What to expect |
| 47 | + |
| 48 | +Configuration files are not automatically merged. When a file is selected, it fully replaces any other config — there is no parent/child layering. To share settings, import the parent config and spread it; see the [monorepo pattern](#monorepo-pattern-share-a-base-config) below. |
| 49 | + |
| 50 | +Command-line options override configuration files. |
| 51 | + |
| 52 | +Passing an explicit config file location using `-c` or `--config` bypasses cwd-based resolution entirely, and only that single configuration file is used — for both `vp lint` and `vp fmt`. |
| 53 | + |
| 54 | +For lint, you can also pass `--disable-nested-config` to stop Oxlint from picking up any stray legacy config files that may exist in the tree: |
| 55 | + |
| 56 | +```bash |
| 57 | +vp lint --disable-nested-config |
| 58 | +vp check --disable-nested-config |
| 59 | +``` |
| 60 | + |
| 61 | +There is no equivalent flag for `vp fmt`; pass `-c` if you need to pin a single format config. |
| 62 | + |
| 63 | +`options.typeAware` and `options.typeCheck` are root-config-only. If either is set in a nested `vite.config.ts` that ends up being selected as the lint config, `vp lint` reports an error. |
| 64 | + |
| 65 | +::: tip Breaking change since the April 2026 release |
| 66 | + |
| 67 | +Earlier versions of Vite+ always injected the workspace-root `vite.config.ts` into every `vp lint` / `vp fmt` invocation, regardless of cwd. Vite+ now lets cwd-based resolution select the config, so running `vp lint` / `vp fmt` from inside a sub-package picks up that sub-package's own `vite.config.ts`. See [#1378](https://github.com/voidzero-dev/vite-plus/pull/1378) for the migration notes. |
| 68 | + |
| 69 | +::: |
| 70 | + |
| 71 | +## Monorepo pattern: share a base config |
| 72 | + |
| 73 | +In a monorepo, you often want one shared baseline at the root and small package-specific adjustments. Import the root `vite.config.ts` from the nested one and spread it: |
| 74 | + |
| 75 | +```ts [my-project/vite.config.ts] |
| 76 | +import { defineConfig } from 'vite-plus'; |
| 77 | + |
| 78 | +export default defineConfig({ |
| 79 | + lint: { |
| 80 | + rules: { |
| 81 | + 'no-debugger': 'error', |
| 82 | + }, |
| 83 | + }, |
| 84 | +}); |
| 85 | +``` |
| 86 | + |
| 87 | +```ts [my-project/package1/vite.config.ts] |
| 88 | +import { defineConfig } from 'vite-plus'; |
| 89 | +import baseConfig from '../vite.config.ts'; |
| 90 | + |
| 91 | +export default defineConfig({ |
| 92 | + ...baseConfig, |
| 93 | + lint: { |
| 94 | + ...baseConfig.lint, |
| 95 | + rules: { |
| 96 | + ...baseConfig.lint?.rules, |
| 97 | + 'no-console': 'off', |
| 98 | + }, |
| 99 | + }, |
| 100 | +}); |
| 101 | +``` |
| 102 | + |
| 103 | +This keeps the shared baseline in one place and makes package configs small and focused. |
0 commit comments