Skip to content

Commit

Permalink
feat: use native runtime to import the config
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy committed Jan 24, 2025
1 parent a4245b0 commit ea8d558
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 30 deletions.
6 changes: 4 additions & 2 deletions docs/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ You can also explicitly specify a config file to use with the `--config` CLI opt
vite --config my-config.js
```

::: tip BUNDLING THE CONFIG
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.
::: tip CONFIG LOADING
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.

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.
:::

## Config Intellisense
Expand Down
38 changes: 19 additions & 19 deletions docs/guide/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,25 @@ vite [root]

#### Options

| Options | |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `--host [host]` | Specify hostname (`string`) |
| `--port <port>` | Specify port (`number`) |
| `--open [path]` | Open browser on startup (`boolean \| string`) |
| `--cors` | Enable CORS (`boolean`) |
| `--strictPort` | Exit if specified port is already in use (`boolean`) |
| `--force` | Force the optimizer to ignore the cache and re-bundle (`boolean`) |
| `-c, --config <file>` | Use specified config file (`string`) |
| `--base <path>` | Public base path (default: `/`) (`string`) |
| `-l, --logLevel <level>` | info \| warn \| error \| silent (`string`) |
| `--clearScreen` | Allow/disable clear screen when logging (`boolean`) |
| `--configLoader <loader>` | Use `bundle` to bundle the config with esbuild or `runner` (experimental) to process it on the fly (default: `bundle`) |
| `--profile` | Start built-in Node.js inspector (check [Performance bottlenecks](/guide/troubleshooting#performance-bottlenecks)) |
| `-d, --debug [feat]` | Show debug logs (`string \| boolean`) |
| `-f, --filter <filter>` | Filter debug logs (`string`) |
| `-m, --mode <mode>` | Set env mode (`string`) |
| `-h, --help` | Display available CLI options |
| `-v, --version` | Display version number |
| Options | |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--host [host]` | Specify hostname (`string`) |
| `--port <port>` | Specify port (`number`) |
| `--open [path]` | Open browser on startup (`boolean \| string`) |
| `--cors` | Enable CORS (`boolean`) |
| `--strictPort` | Exit if specified port is already in use (`boolean`) |
| `--force` | Force the optimizer to ignore the cache and re-bundle (`boolean`) |
| `-c, --config <file>` | Use specified config file (`string`) |
| `--base <path>` | Public base path (default: `/`) (`string`) |
| `-l, --logLevel <level>` | info \| warn \| error \| silent (`string`) |
| `--clearScreen` | Allow/disable clear screen when logging (`boolean`) |
| `--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`) |
| `--profile` | Start built-in Node.js inspector (check [Performance bottlenecks](/guide/troubleshooting#performance-bottlenecks)) |
| `-d, --debug [feat]` | Show debug logs (`string \| boolean`) |
| `-f, --filter <filter>` | Filter debug logs (`string`) |
| `-m, --mode <mode>` | Set env mode (`string`) |
| `-h, --help` | Display available CLI options |
| `-v, --version` | Display version number |

## Build

Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/node/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface GlobalCLIOptions {
l?: LogLevel
logLevel?: LogLevel
clearScreen?: boolean
configLoader?: 'bundle' | 'runner'
configLoader?: 'bundle' | 'runner' | 'native'
d?: boolean | string
debug?: boolean | string
f?: string
Expand Down Expand Up @@ -155,7 +155,7 @@ cli
.option('--clearScreen', `[boolean] allow/disable clear screen when logging`)
.option(
'--configLoader <loader>',
`[string] use 'bundle' to bundle the config with esbuild or 'runner' (experimental) to process it on the fly (default: bundle)`,
`[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)`,
)
.option('-d, --debug [feat]', `[string | boolean] show debug logs`)
.option('-f, --filter <filter>', `[string] filter debug logs`)
Expand Down
30 changes: 24 additions & 6 deletions packages/vite/src/node/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ export interface ResolvedWorkerOptions {
export interface InlineConfig extends UserConfig {
configFile?: string | false
/** @experimental */
configLoader?: 'bundle' | 'runner'
configLoader?: 'bundle' | 'runner' | 'native'
envFile?: false
forceOptimizeDeps?: boolean
}
Expand Down Expand Up @@ -1696,15 +1696,19 @@ export async function loadConfigFromFile(
configRoot: string = process.cwd(),
logLevel?: LogLevel,
customLogger?: Logger,
configLoader: 'bundle' | 'runner' = 'bundle',
configLoader: 'bundle' | 'runner' | 'native' = 'bundle',
): Promise<{
path: string
config: UserConfig
dependencies: string[]
} | null> {
if (configLoader !== 'bundle' && configLoader !== 'runner') {
if (
configLoader !== 'bundle' &&
configLoader !== 'runner' &&
configLoader !== 'native'
) {
throw new Error(
`Unsupported configLoader: ${configLoader}. Accepted values are 'bundle' and 'runner'.`,
`Unsupported configLoader: ${configLoader}. Accepted values are 'bundle', 'runner', and 'native'.`,
)
}

Expand Down Expand Up @@ -1735,7 +1739,11 @@ export async function loadConfigFromFile(

try {
const resolver =
configLoader === 'bundle' ? bundleAndLoadConfigFile : importConfigFile
configLoader === 'bundle'
? bundleAndLoadConfigFile
: configLoader === 'runner'
? runnerImportConfigFile
: nativeImportConfigFile
const { configExport, dependencies } = await resolver(resolvedPath)
debug?.(`config file loaded in ${getTime()}`)

Expand All @@ -1762,7 +1770,17 @@ export async function loadConfigFromFile(
}
}

async function importConfigFile(resolvedPath: string) {
async function nativeImportConfigFile(resolvedPath: string) {
const module = await import(
pathToFileURL(resolvedPath).href + '?t=' + Date.now()
)
return {
configExport: module.default,
dependencies: [],
}
}

async function runnerImportConfigFile(resolvedPath: string) {
const { module, dependencies } = await runnerImport<{
default: UserConfigExport
}>(resolvedPath)
Expand Down
23 changes: 22 additions & 1 deletion playground/config/__tests__/config.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { resolve } from 'node:path'
import { loadConfigFromFile } from 'vite'
import { expect, it } from 'vitest'
import { describe, expect, it } from 'vitest'

const [nvMajor, nvMinor] = process.versions.node.split('.').map(Number)
const isImportAttributesSupported =
Expand Down Expand Up @@ -48,3 +48,24 @@ it.runIf(isImportAttributesSupported)(
`)
},
)

describe('loadConfigFromFile with configLoader: native', () => {
const fixtureRoot = resolve(import.meta.dirname, '../packages/native-import')

it('imports a basic js config', async () => {
const result = await loadConfigFromFile(
{} as any,
resolve(fixtureRoot, 'basic.js'),
fixtureRoot,
undefined,
undefined,
'native',
)
expect(result.config).toMatchInlineSnapshot(`
{
"value": "works",
}
`)
expect(result.dependencies.length).toBe(0)
})
})
3 changes: 3 additions & 0 deletions playground/config/packages/native-import/basic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default {
value: 'works',
}

0 comments on commit ea8d558

Please sign in to comment.