Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use module runner to import the config #18637

Merged
merged 29 commits into from
Jan 23, 2025
Merged
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
547d1c7
feat: use module runner to import the config
sheremet-va Nov 11, 2024
2454b66
chore: todo
sheremet-va Nov 11, 2024
1cf3da7
chore: merge
sheremet-va Nov 11, 2024
df1efe3
chore: use RunnableDevEnvironment instead
sheremet-va Nov 11, 2024
e55e083
chore: make it run faster in tests
sheremet-va Nov 11, 2024
c9e908e
fix: support cjs globals in default modules evaluator
sheremet-va Nov 12, 2024
b4c41d3
feat: add `--bundleConfig` flag to opt-out of bundling
sheremet-va Nov 14, 2024
7c5dcf0
chore: remove cjs support
sheremet-va Nov 14, 2024
aad578d
chore: cleanup
sheremet-va Nov 14, 2024
d8f8771
test: add tests for inlineImport
sheremet-va Nov 14, 2024
0d16f85
chore: update public cjs export
sheremet-va Nov 14, 2024
f295303
refactor: rename bundleConfig to configLoader
sheremet-va Nov 15, 2024
d453876
test: fix windows pathing
sheremet-va Nov 15, 2024
65578af
fix: rename the option in the cli config
sheremet-va Nov 27, 2024
df7d928
docs: add a note to docs
sheremet-va Nov 27, 2024
001f7e9
docs: rename the heading
sheremet-va Nov 27, 2024
1adc486
fix: revert isModuleSyncConditionEnabled, fix types
sheremet-va Nov 28, 2024
5ecd529
test: add comment for moduleDirectories
sheremet-va Nov 28, 2024
275a593
test: add workspace test
sheremet-va Nov 28, 2024
b383651
refactor: mark configLoader as experimental
sheremet-va Dec 1, 2024
14571ac
perf: disable config, envFile and cacheDir
sheremet-va Dec 2, 2024
d847961
chore: remove unused directive
sheremet-va Dec 2, 2024
07867ae
chore: rename to runnerImport, rename test packages
sheremet-va Dec 4, 2024
646a069
lint: remove unesed ts-expect-error
sheremet-va Dec 4, 2024
9b2179a
fix: update other names
bluwy Dec 4, 2024
8669489
refactor: move configLoader validation
sheremet-va Dec 9, 2024
19c5019
test: dynamic import
hi-ogawa Dec 22, 2024
e06731d
Merge branch 'main' into pr/sheremet-va/18637
bluwy Jan 10, 2025
a960fd4
Merge branch 'main' into feat/use-runner-to-import
patak-dev Jan 23, 2025
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
Prev Previous commit
Next Next commit
fix: support cjs globals in default modules evaluator
sheremet-va committed Nov 27, 2024
commit c9e908ea0c5e42a7dbbc0ec52f37775adcb02a3c
18 changes: 17 additions & 1 deletion packages/vite/src/module-runner/esmEvaluator.ts
Original file line number Diff line number Diff line change
@@ -11,8 +11,18 @@ import {
} from './constants'
import type { ModuleEvaluator, ModuleRunnerContext } from './types'

export interface ESModulesEvaluatorOptions {
cjsGlobals?: boolean
startOffset?: number
}

export class ESModulesEvaluator implements ModuleEvaluator {
startOffset = getAsyncFunctionDeclarationPaddingLineCount()
public readonly startOffset: number

constructor(private options: ESModulesEvaluatorOptions = {}) {
this.startOffset =
options.startOffset ?? getAsyncFunctionDeclarationPaddingLineCount()
}

async runInlinedModule(
context: ModuleRunnerContext,
@@ -25,16 +35,22 @@ export class ESModulesEvaluator implements ModuleEvaluator {
ssrImportKey,
ssrDynamicImportKey,
ssrExportAllKey,
'__filename',
'__dirname',
// source map should already be inlined by Vite
'"use strict";' + code,
)

const meta = context[ssrImportMetaKey]

await initModule(
context[ssrModuleExportsKey],
context[ssrImportMetaKey],
context[ssrImportKey],
context[ssrDynamicImportKey],
context[ssrExportAllKey],
this.options.cjsGlobals ? meta.filename : undefined,
this.options.cjsGlobals ? meta.dirname : undefined,
)

Object.seal(context[ssrModuleExportsKey])
5 changes: 4 additions & 1 deletion packages/vite/src/module-runner/index.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,10 @@

export { EvaluatedModules, type EvaluatedModuleNode } from './evaluatedModules'
export { ModuleRunner } from './runner'
export { ESModulesEvaluator } from './esmEvaluator'
export {
ESModulesEvaluator,
type ESModulesEvaluatorOptions,
} from './esmEvaluator'

export { createWebSocketModuleRunnerTransport } from '../shared/moduleRunnerTransport'

129 changes: 71 additions & 58 deletions packages/vite/src/node/config.ts
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import colors from 'picocolors'
import type { Alias, AliasOptions } from 'dep-types/alias'
import type { RollupOptions } from 'rollup'
import picomatch from 'picomatch'
import { ESModulesEvaluator } from 'vite/module-runner'
import type { AnymatchFn } from '../types/anymatch'
import { withTrailingSlash } from '../shared/utils'
import {
@@ -43,7 +44,6 @@ import {
import type { ResolvedServerOptions, ServerOptions } from './server'
import { resolveServerOptions, serverConfigDefaults } from './server'
import { DevEnvironment } from './server/environment'
import type { RunnableDevEnvironment } from './server/environments/runnableEnvironment'
import { createRunnableDevEnvironment } from './server/environments/runnableEnvironment'
import type { WebSocketServer } from './server/ws'
import type { PreviewOptions, ResolvedPreviewOptions } from './preview'
@@ -1658,87 +1658,100 @@ export async function loadConfigFromFile(
return null
}

let environment: RunnableDevEnvironment | undefined

try {
environment = createRunnableDevEnvironment(
'config',
await resolveConfig(
{
configFile: false,
environments: {
config: {
consumer: 'server',
dev: {
moduleRunnerTransform: true,
},
resolve: {
external: true,
},
const { userConfig, dependencies } = await importConfig(resolvedPath)
debug?.(`config file loaded in ${getTime()}`)

const config = await (typeof userConfig === 'function'
? userConfig(configEnv)
: userConfig)
if (!isObject(config)) {
throw new Error(`config must export or return an object.`)
}
return {
path: normalizePath(resolvedPath),
config,
dependencies,
}
} catch (e) {
createLogger(logLevel, { customLogger }).error(
colors.red(`failed to load config from ${resolvedPath}`),
{
error: e,
},
)
throw e
}
}

async function importConfig(resolvedPath: string) {
const environment = createRunnableDevEnvironment(
'config',
// TODO: provide a dummy config?
await resolveConfig(
{
configFile: false,
environments: {
config: {
consumer: 'server',
dev: {
moduleRunnerTransform: true,
},
resolve: {
external: true,
},
},
},
'serve',
),
{
// options: {
// consumer: 'server',
// dev: {
// moduleRunnerTransform: true,
// },
// TODO for some reason this doesn't work, only setting it the config works
// resolve: {
// external: true,
// },
// },
runnerOptions: {
hmr: {
logger: false,
},
},
'serve',
),
{
// options: {
// consumer: 'server',
// dev: {
// moduleRunnerTransform: true,
// },
// TODO for some reason this doesn't work, only setting it the config works
// resolve: {
// external: true,
// },
// },
runnerOptions: {
hmr: {
logger: false,
},
hot: false,
evaluator: new ESModulesEvaluator({
cjsGlobals: true,
}),
},
)
await environment.init()
hot: false,
},
)
await environment.init()
try {
const { default: userConfig } = (await environment.runner.import(
resolvedPath,
)) as {
default: UserConfigExport
}
debug?.(`config file loaded in ${getTime()}`)

const config = await (typeof userConfig === 'function'
? userConfig(configEnv)
: userConfig)
if (!isObject(config)) {
throw new Error(`config must export or return an object.`)
}
const modules = [
...environment.runner.evaluatedModules.fileToModulesMap.entries(),
]
await environment.runner.close()
const dependencies = modules
.filter(([file, modules]) => {
const isExternal = [...modules].some(
const isExternal = [...modules].every(
(m) => !m.meta || 'externalize' in m.meta,
)
return !isExternal && file !== resolvedPath
})
.map(([file]) => file)
return {
path: normalizePath(resolvedPath),
config,
userConfig,
dependencies,
}
} catch (e) {
await environment?.runner.close()
createLogger(logLevel, { customLogger }).error(
colors.red(`failed to load config from ${resolvedPath}`),
{
error: e,
},
)
throw e
} catch (err) {
await environment.close()
throw err
}
}