In create-vue 3.24, what does selecting ESLint generate, why is Oxlint always added with it, and how does the Prettier choice fit in?
answer
- a flat config file
- two linters, one lint script
- rules turned off twice
- formatting kept out of linting
- a deprecated flag says why
basics
~20 sESLint adds a flat eslint.config with the Vue and TypeScript presets, plus Oxlint with an .oxlintrc.json; the lint script runs both. Oxlint is always included and eslint-plugin-oxlint turns off ESLint rules it covers. Prettier adds its own config and a format script.
solid answer
~30 sChoosing ESLint writes a flat `eslint.config` (`.ts` in TypeScript projects) built with `defineConfigWithVueTs` from `@vue/eslint-config-typescript`, the Vue plugin and, with Vitest, `@vitest/eslint-plugin` for test files. Since 3.24 Oxlint is **always** added with ESLint (the old `--oxlint` flag is deprecated): an `.oxlintrc.json` with the correctness category as errors, `lint:oxlint` and `lint:eslint` scripts, and `lint` running both through `run-s`. `eslint-plugin-oxlint`'s `buildFromOxlintConfigFile` goes last and disables ESLint rules Oxlint already checks, so each rule runs once. Prettier adds `.prettierrc.json` and a `format` script; with ESLint it also adds `eslint-config-prettier`'s `skipFormatting`. The experimental Oxfmt choice replaces Prettier.
code
json · 6 lines{
"lint:oxlint": "oxlint . --fix",
"lint:eslint": "eslint . --fix --cache",
"lint": "run-s \"lint:*\"",
"format": "prettier --write --experimental-cli src/"
}go deeper
Recall that ESLint brings a lint script and Prettier brings a format script, and that Oxlint comes along with ESLint.
Explain the flat config, the Oxlint layer that disables duplicate rules, and how skipFormatting separates linting from formatting.
Show you would keep the Oxlint layer last, run lint without --fix in CI, and drop deprecated flags from scaffold scripts.
Decide how much of the generated lint stack becomes a shared config package across Vue repositories, and who owns its upgrades.
## What the ESLint choice writes Selecting ESLint (or `--eslint`) renders several layers: - **`eslint.config`**, a flat config. In a TypeScript project it becomes `eslint.config.ts` (loaded through `jiti`) and uses `defineConfigWithVueTs` with `vueTsConfigs` from `@vue/eslint-config-typescript`; in a JavaScript project it uses the JavaScript core preset. - **Global ignores** for `dist`, `dist-ssr` and `coverage`. - **Tool-specific blocks**: `@vitest/eslint-plugin`'s recommended rules for `src/**/__tests__/*` when Vitest is chosen, and matching blocks for Playwright or Cypress. - **Editor files**: `.editorconfig`, `.gitattributes` and VS Code extension recommendations. - **Oxlint**, always, as described below. ## Why Oxlint comes with it **Oxlint** is a fast linter that implements many common rules natively. create-vue pairs it with ESLint rather than replacing ESLint: the Vue and TypeScript presets it configures are ESLint configs, and Oxlint takes over the rules it can run faster. In 3.24 the `--oxlint` flag is deprecated with the message that Oxlint is now always included when ESLint is selected. The pairing is wired so each rule runs in one tool: 1. `.oxlintrc.json` enables Oxlint's plugins (`eslint`, `typescript` with TS, `unicorn`, `oxc`, `vue`, and `vitest` with Vitest) and sets the `correctness` category to `error`. 2. `eslint-plugin-oxlint`'s `buildFromOxlintConfigFile('.oxlintrc.json')` is appended **last** to the ESLint config; it only disables ESLint rules that Oxlint already covers. 3. The scripts are `lint:oxlint` (`oxlint . --fix`), `lint:eslint` (`eslint . --fix --cache`) and `lint`, which is `run-s "lint:*"`. ## Where Prettier fits | Choice | Files | Scripts | ESLint interaction | |---|---|---|---| | Prettier | `.prettierrc.json` (`semi: false`, `singleQuote: true`, `printWidth: 100`) | `format` | with ESLint, `skipFormatting` from `eslint-config-prettier` | | Oxfmt (experimental) | `.oxfmtrc.json` | `format` | same `skipFormatting` layer | | neither | none | none | none | Prettier does not require ESLint: the formatting layer renders on its own. When both are chosen, `skipFormatting` turns off ESLint's stylistic rules so the linter and the formatter never fight over the same whitespace. `--eslint-with-prettier` is deprecated in favour of `--eslint --prettier`. ## The generated config, top to bottom In a TypeScript project with Vitest, ESLint and Prettier, `eslint.config.ts` is assembled in this order: 1. a block naming the files to lint: `**/*.{vue,ts,mts,tsx}`; 2. `globalIgnores` for build and coverage output; 3. the Vue and TypeScript presets; 4. the Vitest block, scoped to `src/**/__tests__/*`; 5. the Oxlint layer, which only disables rules; 6. `skipFormatting`, which only disables stylistic rules. The two disabling layers sit at the end on purpose: the scaffolder's own comment says these configs only disable rules, so they must be applied last. A commented-out `configureVueProject` call near the top shows how to allow other script languages, such as TSX, in `.vue` files. ## Using it in an internal tool - Run `npm run format` once after install, as the scaffolder's closing message suggests when a formatter was chosen. - In CI, run `npm run lint` without the fix flags if you want a check rather than a rewrite; the generated scripts pass `--fix` because they target local use. - Keep the Oxlint layer last in `eslint.config` when adding your own blocks, or ESLint may re-enable rules Oxlint already checks. - Edit `.oxlintrc.json` rather than `eslint.config` when you want to change a rule Oxlint owns; the ESLint side follows automatically, because the disabling layer is built from that same file. - Install the recommended editor extensions the scaffold lists in `.vscode/extensions.json`, so fixes on save match what the scripts do. - The ESLint script caches results with `--cache`; clear the cache file if a config change seems to have no effect. ## Mistakes worth catching - Passing `--oxlint` in new scripts: deprecated and unnecessary. - Removing `eslint-plugin-oxlint` but keeping Oxlint: every overlapping rule then runs twice. - Adding stylistic ESLint rules alongside Prettier: `skipFormatting` exists to keep formatting out of linting.
- Why is the Oxlint config applied last in eslint.config?`buildFromOxlintConfigFile` only turns rules off. Applied last, it overrides any earlier preset that enabled a rule Oxlint already checks, so the rule runs once, in the faster tool. Blocks you add after it can re-enable duplicates.
- What changes if you pick Oxfmt instead of Prettier?Oxfmt is an experimental choice that replaces Prettier: the project gets `.oxfmtrc.json` and a `format` script for Oxfmt, and no Prettier config. With ESLint, the same `skipFormatting` layer keeps stylistic rules out of the linter.
saying these in an interview costs you the question
- You must pass --oxlint to get Oxlint with ESLint.
- Oxlint replaces ESLint entirely in create-vue projects.
- Choosing Prettier requires choosing ESLint too.
- Every overlapping rule runs in both Oxlint and ESLint.
- The generated config file is a legacy .eslintrc.