Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/e2e-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,11 @@ jobs:
node-version: 24
command: |
vp check --fix
- name: vite-plus-monorepo-overrides
node-version: 24
command: |
vp check --fix
vp run verify
- name: varlet
node-version: 22
command: |
Expand Down
1 change: 1 addition & 0 deletions docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const guideSidebar = [
{ text: 'Creating a Project', link: '/guide/create' },
{ text: 'Migrate to Vite+', link: '/guide/migrate' },
{ text: 'Installing Dependencies', link: '/guide/install' },
{ text: 'Monorepo', link: '/guide/monorepo' },
{ text: 'Environment', link: '/guide/env' },
{ text: 'Why Vite+', link: '/guide/why' },
],
Expand Down
2 changes: 2 additions & 0 deletions docs/config/fmt.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ export default defineConfig({
},
});
```

For package-specific formatting settings in a workspace, use [`fmt.overrides`](/guide/monorepo#format-overrides) from the root `vite.config.ts`.
2 changes: 2 additions & 0 deletions docs/config/lint.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ export default defineConfig({
```

We recommend enabling both `options.typeAware` and `options.typeCheck` so `vp lint` and `vp check` can use the full type-aware path.

For package-specific lint rules in a workspace, use [`lint.overrides`](/guide/monorepo#root-config-with-overrides) from the root `vite.config.ts`.
178 changes: 178 additions & 0 deletions docs/guide/monorepo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Monorepo

Vite+ works well in a monorepo when the shared tool configuration lives in the workspace root. Put the root defaults in `vite.config.ts`, then use `overrides` to apply package-specific lint and format settings.

This is the recommended pattern for shared quality tooling because the root config stays type-safe and composable, while each app or package can still keep its own Vite, Vitest, framework, or runtime files when that is useful.

The examples below come from the runnable [`vite-plus-monorepo-overrides`](https://github.com/why-reproductions-are-required/vite-plus-monorepo-overrides) fixture.

## Root Config With Overrides

Use `lint.overrides` for Oxlint rules that only apply to some packages:

```ts [vite.config.ts]
import { defineConfig } from 'vite-plus';

export default defineConfig({
lint: {
plugins: ['typescript'],
options: {
typeAware: true,
typeCheck: true,
},
rules: {
'no-console': ['error', { allow: ['warn', 'error'] }],
},
overrides: [
{
files: ['apps/web/**', 'packages/ui/**'],
plugins: ['typescript', 'react'],
rules: {
'react/self-closing-comp': 'error',
},
},
{
files: ['apps/api/**'],
env: {
node: true,
},
rules: {
'no-console': 'off',
},
},
{
files: ['**/*.test.ts', '**/*.spec.ts'],
plugins: ['typescript', 'vitest'],
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure the plugins example actually exists and is not fabricated

rules: {
'@typescript-eslint/no-explicit-any': 'off',
'vitest/no-disabled-tests': 'error',
},
},
],
},
});
```

Globs are resolved from the root `vite.config.ts`, so use workspace paths such as `apps/web/**`, `apps/api/**`, and `packages/ui/**`.

::: tip
When a `lint.overrides` entry sets `plugins`, include the plugins needed for that file group. If you omit `plugins`, the override uses the base `lint.plugins` value.
:::

## Format Overrides

Use `fmt.overrides` for file or package-specific Oxfmt options. Formatter overrides put their settings under `options`:

```ts [vite.config.ts]
import { defineConfig } from 'vite-plus';

export default defineConfig({
fmt: {
singleQuote: true,
semi: true,
overrides: [
{
files: ['apps/api/**'],
options: {
printWidth: 120,
},
},
{
files: ['**/*.md'],
options: {
proseWrap: 'always',
},
},
],
},
});
```

## Splitting Config Files

You can still split configuration across your repository. Export normal JavaScript objects from nearby files, import them in the root config, and merge them into the matching override.

```ts [tooling/lint/react.ts]
import type { OxlintOverride } from 'vite-plus/lint';

export const reactLint = {
plugins: ['typescript', 'react'],
rules: {
'react/self-closing-comp': 'error',
},
} satisfies Omit<OxlintOverride, 'files'>;
```

```ts [tooling/lint/node.ts]
import type { OxlintOverride } from 'vite-plus/lint';

export const nodeLint = {
env: {
node: true,
},
rules: {
'no-console': 'off',
},
} satisfies Omit<OxlintOverride, 'files'>;
```

```ts [vite.config.ts]
import { defineConfig } from 'vite-plus';

import { nodeLint } from './tooling/lint/node';
import { reactLint } from './tooling/lint/react';

export default defineConfig({
lint: {
plugins: ['typescript'],
options: {
typeAware: true,
typeCheck: true,
},
overrides: [
{
files: ['apps/web/**', 'packages/ui/**'],
...reactLint,
},
{
files: ['apps/api/**'],
...nodeLint,
},
],
},
});
```

This keeps the behavior centralized while letting each team or package own the pieces of config it needs.

## App Commands

The root `vite.config.ts` is most valuable for shared linting, formatting, staged checks, and task definitions. For project-specific development, build, and test behavior, use the setup that best matches each app:

- Pass a folder to built-in Vite commands when you want to target one app:

```bash
vp dev apps/web
vp build apps/web
```

- Keep package-specific scripts in each package when the command differs per app:

```json [apps/api/package.json]
{
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc -p tsconfig.json"
}
}
```

- Run scripts across the workspace with `vp run`:

```bash
vp run -r build
vp run -r --parallel dev
vp run --filter ./apps/web build
```

See the [Run guide](/guide/run) for recursive, parallel, filtered, and cached workspace tasks.
6 changes: 6 additions & 0 deletions ecosystem-ci/repo.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@
"hash": "6192f60653c124ae068efaf5d7d0a4134c95edbd",
"forceFreshMigration": true
},
"vite-plus-monorepo-overrides": {
"repository": "https://github.com/why-reproductions-are-required/vite-plus-monorepo-overrides.git",
"branch": "main",
"hash": "d89fe8f6479679e32e7a105fad85a2139beb2802",
"forceFreshMigration": true
},
"varlet": {
"repository": "https://github.com/varletjs/varlet.git",
"branch": "dev",
Expand Down
Loading