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
6 changes: 2 additions & 4 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default {
}
```

Note Vite supports using ES modules syntax in the config file even if the project is not using native Node ESM, e.g. `"type": "module"` in `package.json`. In this case, the config file is auto pre-processed before load.
Note that to use ES modules syntax in the config file, it should be in a file detected as ESM by Node.js, e.g. `.mjs` or `.js` with `"type": "module"` in closest `package.json`.

You can also explicitly specify a config file to use with the `--config` CLI option (resolved relative to `cwd`):

Expand All @@ -25,9 +25,7 @@ vite --config my-config.js
<ScrimbaLink href="https://scrimba.com/intro-to-vite-c03p6pbbdq/~05jg?via=vite" title="Configuring Vite">Watch an interactive lesson on Scrimba</ScrimbaLink>

::: tip CONFIG LOADING
By default, Vite uses [Rolldown](https://rolldown.rs/) to bundle the config into a temporary file and load it. This may cause issues when importing TypeScript files in a monorepo. If you encounter any issues with this approach, you can specify `--configLoader runner` to use the [module runner](/guide/api-environment-runtimes.html#modulerunner) instead, which will not create a temporary config and will transform any files on the fly. Note that module runner doesn't support CJS in config files, but external CJS packages should work as usual.

Alternatively, if you're using an environment that supports TypeScript (e.g. `node --experimental-strip-types`), or if you're only writing plain JavaScript, you can specify `--configLoader native` to use the environment's native runtime to load the config file. Note that updates to modules imported by the config file are not detected and hence would not auto-restart the Vite server.
By default, Vite uses [Rolldown](https://rolldown.rs/) to bundle the config into a temporary file and load it. If you're using an environment that supports TypeScript (e.g. Node 22.18+), or if you're only writing plain JavaScript, you can specify `--configLoader native` to use the environment's native runtime to load the config file. `configLoader: 'native'` is planned to become the default in a future major version.
:::

## Config Intellisense
Expand Down
35 changes: 35 additions & 0 deletions packages/vite/LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1219,6 +1219,13 @@ Repository: https://github.com/micromatch/is-glob
---------------------------------------

## is-reference
License: MIT
By: Rich Harris
Repository: https://github.com/Rich-Harris/is-reference

---------------------------------------

## isexe, which
License: ISC
By: Isaac Z. Schlueter
Expand Down Expand Up @@ -2285,3 +2292,31 @@ Repository: https://github.com/websockets/ws
> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
> IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---------------------------------------

## zimmerframe
License: MIT
Repository: https://github.com/sveltejs/zimmerframe

> MIT License
>
> Copyright (c) 2023 [these people](https://github.com/Rich-Harris/zimmerframe/graphs/contributors)
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all
> copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.
139 changes: 139 additions & 0 deletions packages/vite/src/node/__tests__/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import http from 'node:http'
import os from 'node:os'
import path from 'node:path'
import fs from 'node:fs'
import { stripVTControlCharacters } from 'node:util'
import { afterEach, assert, describe, expect, test, vi } from 'vitest'
import type { InlineConfig, PluginOption } from '..'
import type { UserConfig, UserConfigExport } from '../config'
Expand Down Expand Up @@ -1371,6 +1372,144 @@ test('preTransformRequests', async () => {
describe('loadConfigFromFile', () => {
const fixtures = path.resolve(import.meta.dirname, './fixtures/config')

describe('native-incompatibility warnings', () => {
const compatRoot = path.resolve(fixtures, './native-compat')

// eslint-disable-next-line n/no-unsupported-features/node-builtins
const supportsTypeStripping = !!process.features.typescript

const loadWithWarnings = async (
dir: string,
configFile = 'vite.config.js',
) => {
const logger = createLogger('info')
const warn = vi.spyOn(logger, 'warn').mockImplementation(() => {})
const root = path.resolve(compatRoot, dir)
await loadConfigFromFile(
{} as any,
path.resolve(root, configFile),
root,
undefined,
logger,
'bundle',
)
const messages = warn.mock.calls.map((c) =>
stripVTControlCharacters(c[0]),
)
warn.mockRestore()
return messages
}

test('warns on __dirname / __filename', async () => {
const messages = await loadWithWarnings('dirname')
expect(messages).toMatchInlineSnapshot(`
[
"(!) Your Vite config uses features that are unsupported by \`configLoader: 'native'\`, which is planned to become the default in a future major version of Vite:
- \`__dirname\` (vite.config.js:3). Use \`import.meta.dirname\` instead
- \`__filename\` (vite.config.js:4). Use \`import.meta.filename\` instead
Set \`VITE_CONFIG_NATIVE_IGNORE_WARNING=true\` to suppress this warning.",
]
`)
})

// uses a `.ts` config with TypeScript-only syntax; skipped on Node
// versions without type stripping support
test.skipIf(!supportsTypeStripping)(
'warns on __dirname in a config using TypeScript syntax',
async () => {
const messages = await loadWithWarnings('ts-syntax', 'vite.config.ts')
expect(messages).toMatchInlineSnapshot(`
[
"(!) Your Vite config uses features that are unsupported by \`configLoader: 'native'\`, which is planned to become the default in a future major version of Vite:
- \`__dirname\` (vite.config.ts:10). Use \`import.meta.dirname\` instead
Set \`VITE_CONFIG_NATIVE_IGNORE_WARNING=true\` to suppress this warning.",
]
`)
},
)

test('warns on extension-less import', async () => {
const messages = await loadWithWarnings('extensionless')
expect(messages).toMatchInlineSnapshot(`
[
"(!) Your Vite config uses features that are unsupported by \`configLoader: 'native'\`, which is planned to become the default in a future major version of Vite:
- import "./helper" without a file extension (vite.config.js:1). Add the file extension
Set \`VITE_CONFIG_NATIVE_IGNORE_WARNING=true\` to suppress this warning.",
]
`)
})

test('warns on directory-index import', async () => {
const messages = await loadWithWarnings('directory-index')
expect(messages).toMatchInlineSnapshot(`
[
"(!) Your Vite config uses features that are unsupported by \`configLoader: 'native'\`, which is planned to become the default in a future major version of Vite:
- import "./plugins" resolves to a directory index (vite.config.js:1). Import the index file directly
Set \`VITE_CONFIG_NATIVE_IGNORE_WARNING=true\` to suppress this warning.",
]
`)
})

test('warns on JSON import without attributes', async () => {
const messages = await loadWithWarnings('json')
expect(messages).toMatchInlineSnapshot(`
[
"(!) Your Vite config uses features that are unsupported by \`configLoader: 'native'\`, which is planned to become the default in a future major version of Vite:
- JSON import "./data.json" without import attributes (vite.config.js:1). Add \`with { type: 'json' }\`
Set \`VITE_CONFIG_NATIVE_IGNORE_WARNING=true\` to suppress this warning.",
]
`)
})

test('does not warn on JSON import with attributes', async () => {
expect(await loadWithWarnings('json-ok')).toHaveLength(0)
})

test('warns on an extension-less import that resolves to JSON', async () => {
const messages = await loadWithWarnings('json-extensionless')
expect(messages).toMatchInlineSnapshot(`
[
"(!) Your Vite config uses features that are unsupported by \`configLoader: 'native'\`, which is planned to become the default in a future major version of Vite:
- import "./foo" resolves to a JSON file (vite.config.js:1). Import it with a \`.json\` extension and \`with { type: 'json' }\`
Set \`VITE_CONFIG_NATIVE_IGNORE_WARNING=true\` to suppress this warning.",
]
`)
})

test('does not warn on a native-compatible config', async () => {
expect(await loadWithWarnings('clean')).toHaveLength(0)
})

test('does not warn for a CJS config using __dirname', async () => {
expect(await loadWithWarnings('cjs', 'vite.config.cjs')).toHaveLength(0)
})

test('warns for an ESM file imported by a CJS config', async () => {
const messages = await loadWithWarnings(
'cjs-imports-esm',
'vite.config.cjs',
)
expect(messages).toMatchInlineSnapshot(`
[
"(!) Your Vite config uses features that are unsupported by \`configLoader: 'native'\`, which is planned to become the default in a future major version of Vite:
- \`__dirname\` (esm-helper.mjs:1). Use \`import.meta.dirname\` instead
Set \`VITE_CONFIG_NATIVE_IGNORE_WARNING=true\` to suppress this warning.",
]
`)
})

test('warns on ESM syntax in a config under a `type: commonjs` package', async () => {
const messages = await loadWithWarnings('esm-in-commonjs-pkg')
expect(messages).toMatchInlineSnapshot(`
[
"(!) Your Vite config uses features that are unsupported by \`configLoader: 'native'\`, which is planned to become the default in a future major version of Vite:
- ESM syntax in a file loaded as CommonJS (vite.config.js:1). Use a \`.mjs\` extension or set \`"type": "module"\` in the closest package.json
Set \`VITE_CONFIG_NATIVE_IGNORE_WARNING=true\` to suppress this warning.",
]
`)
})
})

describe('load default files', () => {
const root = path.resolve(fixtures, './loadConfigFromFile')

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import moduleCondition from '@vite/test-config-plugin-module-condition'
import { array } from '../siblings/foo'
import { array } from '../siblings/foo.js'
import importsField from '#imports-field'

export default {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const dir = JSON.stringify(__dirname)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const { dir } = require('./esm-helper.mjs')

module.exports = { define: { DIR: dir } }
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
define: {
__DIR__: JSON.stringify(__dirname),
__FILE__: JSON.stringify(__filename),
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const value = 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { value } from './helper.js'

export default {
define: {
DIR: JSON.stringify(import.meta.dirname),
VALUE: value,
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const plugins = []
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { plugins } from './plugins'

export default { plugins }
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
define: {
__DIR__: JSON.stringify(__dirname),
__FILE__: JSON.stringify(__filename),
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "@vitejs/test-native-compat-commonjs",
"type": "commonjs",
"private": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { defineConfig } from 'vite'

export default defineConfig({})
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const value = 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { value } from './helper'

export default { define: { VALUE: value } }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "value": 1 }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import data from './foo'

export default { define: { DATA: JSON.stringify(data) } }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "value": 1 }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import data from './data.json' with { type: 'json' }

export default { define: { DATA: JSON.stringify(data) } }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "value": 1 }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import data from './data.json'

export default { define: { DATA: JSON.stringify(data) } }
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "@vitejs/test-native-compat",
"type": "module",
"private": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
enum Mode {
Dev,
Prod,
}

const value = 1 as number

export default {
define: {
__DIR__: JSON.stringify(__dirname),
MODE: Mode.Dev,
VALUE: value,
},
}
Loading
Loading