Skip to content

Commit 7c2a794

Browse files
authored
feat: use native runtime to import the config (#19178)
1 parent fcd5785 commit 7c2a794

File tree

6 files changed

+74
-30
lines changed

6 files changed

+74
-30
lines changed

docs/config/index.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ You can also explicitly specify a config file to use with the `--config` CLI opt
2222
vite --config my-config.js
2323
```
2424

25-
::: tip BUNDLING THE CONFIG
26-
By default, Vite uses `esbuild` to bundle the config into a temporary file. This can 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 instead - it 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.
25+
::: tip CONFIG LOADING
26+
By default, Vite uses `esbuild` 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.
27+
28+
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.
2729
:::
2830

2931
## Config Intellisense

docs/guide/cli.md

+19-19
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,25 @@ vite [root]
1414

1515
#### Options
1616

17-
| Options | |
18-
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
19-
| `--host [host]` | Specify hostname (`string`) |
20-
| `--port <port>` | Specify port (`number`) |
21-
| `--open [path]` | Open browser on startup (`boolean \| string`) |
22-
| `--cors` | Enable CORS (`boolean`) |
23-
| `--strictPort` | Exit if specified port is already in use (`boolean`) |
24-
| `--force` | Force the optimizer to ignore the cache and re-bundle (`boolean`) |
25-
| `-c, --config <file>` | Use specified config file (`string`) |
26-
| `--base <path>` | Public base path (default: `/`) (`string`) |
27-
| `-l, --logLevel <level>` | info \| warn \| error \| silent (`string`) |
28-
| `--clearScreen` | Allow/disable clear screen when logging (`boolean`) |
29-
| `--configLoader <loader>` | Use `bundle` to bundle the config with esbuild or `runner` (experimental) to process it on the fly (default: `bundle`) |
30-
| `--profile` | Start built-in Node.js inspector (check [Performance bottlenecks](/guide/troubleshooting#performance-bottlenecks)) |
31-
| `-d, --debug [feat]` | Show debug logs (`string \| boolean`) |
32-
| `-f, --filter <filter>` | Filter debug logs (`string`) |
33-
| `-m, --mode <mode>` | Set env mode (`string`) |
34-
| `-h, --help` | Display available CLI options |
35-
| `-v, --version` | Display version number |
17+
| Options | |
18+
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
19+
| `--host [host]` | Specify hostname (`string`) |
20+
| `--port <port>` | Specify port (`number`) |
21+
| `--open [path]` | Open browser on startup (`boolean \| string`) |
22+
| `--cors` | Enable CORS (`boolean`) |
23+
| `--strictPort` | Exit if specified port is already in use (`boolean`) |
24+
| `--force` | Force the optimizer to ignore the cache and re-bundle (`boolean`) |
25+
| `-c, --config <file>` | Use specified config file (`string`) |
26+
| `--base <path>` | Public base path (default: `/`) (`string`) |
27+
| `-l, --logLevel <level>` | info \| warn \| error \| silent (`string`) |
28+
| `--clearScreen` | Allow/disable clear screen when logging (`boolean`) |
29+
| `--configLoader <loader>` | Use `bundle` to bundle the config with esbuild, or `runner` (experimental) to process it on the fly, or `native` (experimental) to load using the native runtime (default: `bundle`) |
30+
| `--profile` | Start built-in Node.js inspector (check [Performance bottlenecks](/guide/troubleshooting#performance-bottlenecks)) |
31+
| `-d, --debug [feat]` | Show debug logs (`string \| boolean`) |
32+
| `-f, --filter <filter>` | Filter debug logs (`string`) |
33+
| `-m, --mode <mode>` | Set env mode (`string`) |
34+
| `-h, --help` | Display available CLI options |
35+
| `-v, --version` | Display version number |
3636

3737
## Build
3838

packages/vite/src/node/cli.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface GlobalCLIOptions {
2323
l?: LogLevel
2424
logLevel?: LogLevel
2525
clearScreen?: boolean
26-
configLoader?: 'bundle' | 'runner'
26+
configLoader?: 'bundle' | 'runner' | 'native'
2727
d?: boolean | string
2828
debug?: boolean | string
2929
f?: string
@@ -155,7 +155,7 @@ cli
155155
.option('--clearScreen', `[boolean] allow/disable clear screen when logging`)
156156
.option(
157157
'--configLoader <loader>',
158-
`[string] use 'bundle' to bundle the config with esbuild or 'runner' (experimental) to process it on the fly (default: bundle)`,
158+
`[string] use 'bundle' to bundle the config with esbuild, or 'runner' (experimental) to process it on the fly, or 'native' (experimental) to load using the native runtime (default: bundle)`,
159159
)
160160
.option('-d, --debug [feat]', `[string | boolean] show debug logs`)
161161
.option('-f, --filter <filter>', `[string] filter debug logs`)

packages/vite/src/node/config.ts

+24-6
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ export interface ResolvedWorkerOptions {
546546
export interface InlineConfig extends UserConfig {
547547
configFile?: string | false
548548
/** @experimental */
549-
configLoader?: 'bundle' | 'runner'
549+
configLoader?: 'bundle' | 'runner' | 'native'
550550
envFile?: false
551551
forceOptimizeDeps?: boolean
552552
}
@@ -1702,15 +1702,19 @@ export async function loadConfigFromFile(
17021702
configRoot: string = process.cwd(),
17031703
logLevel?: LogLevel,
17041704
customLogger?: Logger,
1705-
configLoader: 'bundle' | 'runner' = 'bundle',
1705+
configLoader: 'bundle' | 'runner' | 'native' = 'bundle',
17061706
): Promise<{
17071707
path: string
17081708
config: UserConfig
17091709
dependencies: string[]
17101710
} | null> {
1711-
if (configLoader !== 'bundle' && configLoader !== 'runner') {
1711+
if (
1712+
configLoader !== 'bundle' &&
1713+
configLoader !== 'runner' &&
1714+
configLoader !== 'native'
1715+
) {
17121716
throw new Error(
1713-
`Unsupported configLoader: ${configLoader}. Accepted values are 'bundle' and 'runner'.`,
1717+
`Unsupported configLoader: ${configLoader}. Accepted values are 'bundle', 'runner', and 'native'.`,
17141718
)
17151719
}
17161720

@@ -1741,7 +1745,11 @@ export async function loadConfigFromFile(
17411745

17421746
try {
17431747
const resolver =
1744-
configLoader === 'bundle' ? bundleAndLoadConfigFile : importConfigFile
1748+
configLoader === 'bundle'
1749+
? bundleAndLoadConfigFile
1750+
: configLoader === 'runner'
1751+
? runnerImportConfigFile
1752+
: nativeImportConfigFile
17451753
const { configExport, dependencies } = await resolver(resolvedPath)
17461754
debug?.(`config file loaded in ${getTime()}`)
17471755

@@ -1768,7 +1776,17 @@ export async function loadConfigFromFile(
17681776
}
17691777
}
17701778

1771-
async function importConfigFile(resolvedPath: string) {
1779+
async function nativeImportConfigFile(resolvedPath: string) {
1780+
const module = await import(
1781+
pathToFileURL(resolvedPath).href + '?t=' + Date.now()
1782+
)
1783+
return {
1784+
configExport: module.default,
1785+
dependencies: [],
1786+
}
1787+
}
1788+
1789+
async function runnerImportConfigFile(resolvedPath: string) {
17721790
const { module, dependencies } = await runnerImport<{
17731791
default: UserConfigExport
17741792
}>(resolvedPath)

playground/config/__tests__/config.spec.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { resolve } from 'node:path'
22
import { loadConfigFromFile } from 'vite'
3-
import { expect, it } from 'vitest'
3+
import { describe, expect, it } from 'vitest'
44

55
const [nvMajor, nvMinor] = process.versions.node.split('.').map(Number)
66
const isImportAttributesSupported =
@@ -48,3 +48,24 @@ it.runIf(isImportAttributesSupported)(
4848
`)
4949
},
5050
)
51+
52+
describe('loadConfigFromFile with configLoader: native', () => {
53+
const fixtureRoot = resolve(import.meta.dirname, '../packages/native-import')
54+
55+
it('imports a basic js config', async () => {
56+
const result = await loadConfigFromFile(
57+
{} as any,
58+
resolve(fixtureRoot, 'basic.js'),
59+
fixtureRoot,
60+
undefined,
61+
undefined,
62+
'native',
63+
)
64+
expect(result.config).toMatchInlineSnapshot(`
65+
{
66+
"value": "works",
67+
}
68+
`)
69+
expect(result.dependencies.length).toBe(0)
70+
})
71+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default {
2+
value: 'works',
3+
}

0 commit comments

Comments
 (0)