Skip to content
Merged
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
12 changes: 12 additions & 0 deletions docs/config/shared-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,18 @@ Enabling this setting causes vite to determine file identity by the original fil

Enables the tsconfig paths resolution feature. `paths` option in `tsconfig.json` will be used to resolve imports. See [Features](/guide/features.md#paths) for more details.

`paths` only applies to a file matched by a `tsconfig.json` through its `files` or `include`. Non-JS extension files should be explicitly listed in them, since a bare `"src"` or `"**/*"` `include` only matches TS/JS extensions, aligning with TypeScript's behavior. For example, to use a `paths` alias inside a CSS file (such as `@import '@/foo.css'`), list those files in `files`, or add an explicit extension to `include`:

```json [tsconfig.json]
{
"include": ["src", "src/**/*.css", "src/**/*.scss"]
}
```

::: warning Less is not supported
`resolve.tsconfigPaths` does not apply inside `.less` files. Less only gives Vite the importing file's directory, not the file itself, so Vite cannot find the `tsconfig.json` that matches it. Use a relative path or [`resolve.alias`](#resolve-alias) for `@import` in Less.
:::

## html.cspNonce

- **Type:** `string`
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ This option is only partially supported. Full support requires type inference by

- [TypeScript documentation](https://www.typescriptlang.org/tsconfig/#paths)

`resolve.tsconfigPaths: true` can be specified to tell Vite to use the `paths` option in `tsconfig.json` to resolve imports.
[`resolve.tsconfigPaths: true`](/config/shared-options.md#resolve-tsconfigpaths) can be specified to tell Vite to use the `paths` option in `tsconfig.json` to resolve imports.

Note that this feature has a performance cost and is [discouraged by the TypeScript team to use this option to change the behavior of the external tools](https://www.typescriptlang.org/tsconfig/#paths:~:text=Note%20that%20this%20feature%20does%20not%20change%20how%20import%20paths%20are%20emitted%20by%20tsc%2C%20so%20paths%20should%20only%20be%20used%20to%20inform%20TypeScript%20that%20another%20tool%20has%20this%20mapping%20and%20will%20use%20it%20at%20runtime%20or%20when%20bundling.).

Expand Down
10 changes: 8 additions & 2 deletions packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1547,7 +1547,7 @@ async function compilePostCSS(
if (needInlineImport) {
postcssPlugins.unshift(
(await importPostcssImport()).default({
async resolve(id, basedir) {
async resolve(id, basedir, _importOptions, atRule) {
const publicFile = checkPublicFile(
id,
environment.getTopLevelConfig(),
Expand All @@ -1559,7 +1559,10 @@ async function compilePostCSS(
const resolved = await atImportResolvers.css(
environment,
id,
path.join(basedir, '*'),
// The `source` is only absent for an `@import` injected by another plugin
// (a node with no source), in which case the resolver falls back to
// the project root.
atRule.source?.input.file,
Comment thread
sapphi-red marked this conversation as resolved.
)

if (resolved) {
Expand Down Expand Up @@ -2787,6 +2790,9 @@ const makeLessWorker = (
const resolved = await resolvers.less(
environment,
filename,
// Less only exposes the importer's directory, not the file, so Vite can't
// pass a real importer like CSS/Sass do. `resolve.tsconfigPaths` therefore
// does not apply inside `.less` files. See the `resolve.tsconfigPaths` docs.
path.join(dir, '*'),
Comment thread
sapphi-red marked this conversation as resolved.
)
if (!resolved) return undefined
Expand Down
1 change: 1 addition & 0 deletions packages/vite/src/types/shims.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ declare module 'postcss-import' {
id: string,
basedir: string,
importOptions: any,
atRule: import('postcss').AtRule,
) => string | string[] | Promise<string | string[]>
load: (id: string) => Promise<string>
nameLayer: (index: number, rootFilename: string) => string
Expand Down
17 changes: 16 additions & 1 deletion playground/resolve-tsconfig-paths/__tests__/resolve.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect, test } from 'vitest'
import { page } from '~utils'
import { getColor, page } from '~utils'

test('import from .ts', async () => {
await expect.poll(() => page.textContent('.ts')).toMatch('[success]')
Expand All @@ -21,3 +21,18 @@ test('nested tsconfig.json & references / include works', async () => {
await expect.poll(() => page.textContent('.nested-a')).toMatch('[success]')
await expect.poll(() => page.textContent('.nested-b')).toMatch('[success]')
})

test('css @import resolves tsconfig paths', async () => {
await expect.poll(() => getColor('.tsconfig-paths-css')).toBe('darkcyan')
})

test('sass @use resolves tsconfig paths', async () => {
await expect.poll(() => getColor('.tsconfig-paths-scss')).toBe('seagreen')
})

// `resolve.tsconfigPaths` is not supported inside `.less` files. The aliased
// `@import (optional) '@/less-imported.less'` cannot resolve (even with
// `**/*.less` in `include`), so it is skipped and the color stays `navy`.
test('less @import does not resolve tsconfig paths (unsupported)', async () => {
await expect.poll(() => getColor('.tsconfig-paths-less')).toBe('navy')
})
11 changes: 11 additions & 0 deletions playground/resolve-tsconfig-paths/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,18 @@ <h2>Nested tsconfig.json & references / include works</h2>
<p class="nested-a"></p>
<p class="nested-b"></p>

<h2>CSS / Sass @import resolves tsconfig paths (Less does not)</h2>
<p class="tsconfig-paths-css">This text should be darkcyan</p>
<p class="tsconfig-paths-scss">This text should be seagreen</p>
<p class="tsconfig-paths-less">
This text should stay navy (Less is unsupported)
</p>

<script type="module">
import '@/style.css'
import '@/style.scss'
import '@/style.less'

function text(selector, text) {
document.querySelector(selector).textContent = text
}
Expand Down
4 changes: 4 additions & 0 deletions playground/resolve-tsconfig-paths/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@
"build": "vite build",
"debug": "node --inspect-brk ../../packages/vite/bin/vite",
"preview": "vite preview"
},
"devDependencies": {
"less": "^4.6.6",
"sass": "^1.101.0"
}
}
3 changes: 3 additions & 0 deletions playground/resolve-tsconfig-paths/src/imported.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.tsconfig-paths-css {
color: darkcyan;
}
4 changes: 4 additions & 0 deletions playground/resolve-tsconfig-paths/src/less-imported.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Only applied if the `@/less-imported.less` alias resolves, which it must not.
.tsconfig-paths-less {
color: tomato;
}
3 changes: 3 additions & 0 deletions playground/resolve-tsconfig-paths/src/scss-imported.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.tsconfig-paths-scss {
color: seagreen;
}
2 changes: 2 additions & 0 deletions playground/resolve-tsconfig-paths/src/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/* `@import` with a tsconfig `paths` alias must resolve from a CSS importer */
@import '@/imported.css';
9 changes: 9 additions & 0 deletions playground/resolve-tsconfig-paths/src/style.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.tsconfig-paths-less {
color: navy;
}

// `resolve.tsconfigPaths` does NOT apply inside `.less` files (Less only gives
// Vite the importer's directory, not the file). Even though `**/*.less` is in
// the tsconfig `include`, this aliased import cannot resolve, so it is skipped
// via `(optional)` and the color stays `navy` instead of becoming `tomato`.
@import (optional) '@/less-imported.less';
2 changes: 2 additions & 0 deletions playground/resolve-tsconfig-paths/src/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// `@use` with a tsconfig `paths` alias must resolve from a Sass importer
@use '@/scss-imported' as *;
2 changes: 1 addition & 1 deletion playground/resolve-tsconfig-paths/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"#/*": ["./src/*"]
}
},
"include": ["**/*", "index.html"],
"include": ["**/*", "**/*.css", "**/*.scss", "**/*.less", "index.html"],
"exclude": ["./__tests__"]
}
9 changes: 8 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading