mirror of
https://github.com/vitejs/vite.git
synced 2024-11-21 14:48:41 +00:00
refactor: remove build time pre-bundling (#15184)
Co-authored-by: 翠 / green <green@sapphi.red> Co-authored-by: Bjorn Lu <bjornlu.dev@gmail.com>
This commit is contained in:
parent
fdc142cd27
commit
757844f0bd
@ -64,16 +64,17 @@ Set to `true` to force dependency pre-bundling, ignoring previously cached optim
|
||||
|
||||
## optimizeDeps.disabled
|
||||
|
||||
- **Deprecated**
|
||||
- **Experimental:** [Give Feedback](https://github.com/vitejs/vite/discussions/13839)
|
||||
- **Type:** `boolean | 'build' | 'dev'`
|
||||
- **Default:** `'build'`
|
||||
|
||||
Disables dependencies optimizations, `true` disables the optimizer during build and dev. Pass `'build'` or `'dev'` to only disable the optimizer in one of the modes. Dependency optimization is enabled by default in dev only.
|
||||
This option is deprecated. As of Vite 5.1, pre-bundling of dependencies during build have been removed. Setting `optimizeDeps.disabled` to `true` or `'dev'` disables the optimizer, and configured to `false` or `'build'` leaves the optimizer during dev enabled.
|
||||
|
||||
To disable the optimizer completely, use `optimizeDeps.noDiscovery: true` to disallow automatic discovery of dependencies and leave `optimizeDeps.include` undefined or empty.
|
||||
|
||||
:::warning
|
||||
Optimizing dependencies in build mode is **experimental**. If enabled, it removes one of the most significant differences between dev and prod. [`@rollup/plugin-commonjs`](https://github.com/rollup/plugins/tree/master/packages/commonjs) is no longer needed in this case since esbuild converts CJS-only dependencies to ESM.
|
||||
|
||||
If you want to try this build strategy, you can use `optimizeDeps.disabled: false`. `@rollup/plugin-commonjs` can be removed by passing `build.commonjsOptions: { include: [] }`.
|
||||
Optimizing dependencies during build time was an **experimental** feature. Projects trying out this strategy also removed `@rollup/plugin-commonjs` using `build.commonjsOptions: { include: [] }`. If you did so, a warning will guide you to re-enable it to support CJS only packages while bundling.
|
||||
:::
|
||||
|
||||
## optimizeDeps.needsInterop
|
||||
|
@ -26,7 +26,6 @@
|
||||
"test": "run-s test-unit test-serve test-build",
|
||||
"test-serve": "vitest run -c vitest.config.e2e.ts",
|
||||
"test-build": "VITE_TEST_BUILD=1 vitest run -c vitest.config.e2e.ts",
|
||||
"test-build-without-plugin-commonjs": "VITE_TEST_WITHOUT_PLUGIN_COMMONJS=1 pnpm test-build",
|
||||
"test-unit": "vitest run",
|
||||
"test-docs": "pnpm run docs-build",
|
||||
"debug-serve": "VITE_DEBUG_SERVE=1 vitest run -c vitest.config.e2e.ts",
|
||||
|
@ -467,20 +467,6 @@ export async function resolveConfig(
|
||||
const userPlugins = [...prePlugins, ...normalPlugins, ...postPlugins]
|
||||
config = await runConfigHook(config, userPlugins, configEnv)
|
||||
|
||||
// If there are custom commonjsOptions, don't force optimized deps for this test
|
||||
// even if the env var is set as it would interfere with the playground specs.
|
||||
if (
|
||||
!config.build?.commonjsOptions &&
|
||||
process.env.VITE_TEST_WITHOUT_PLUGIN_COMMONJS
|
||||
) {
|
||||
config = mergeConfig(config, {
|
||||
optimizeDeps: { disabled: false },
|
||||
ssr: { optimizeDeps: { disabled: false } },
|
||||
})
|
||||
config.build ??= {}
|
||||
config.build.commonjsOptions = { include: [] }
|
||||
}
|
||||
|
||||
// Define logger
|
||||
const logger = createLogger(config.logLevel, {
|
||||
allowClearScreen: config.clearScreen,
|
||||
@ -780,7 +766,6 @@ export async function resolveConfig(
|
||||
packageCache,
|
||||
createResolver,
|
||||
optimizeDeps: {
|
||||
disabled: 'build',
|
||||
...optimizeDeps,
|
||||
esbuildOptions: {
|
||||
preserveSymlinks: resolveOptions.preserveSymlinks,
|
||||
@ -816,6 +801,13 @@ export async function resolveConfig(
|
||||
.map((hook) => hook(resolved)),
|
||||
)
|
||||
|
||||
optimizeDepsDisabledBackwardCompatibility(resolved, resolved.optimizeDeps)
|
||||
optimizeDepsDisabledBackwardCompatibility(
|
||||
resolved,
|
||||
resolved.ssr.optimizeDeps,
|
||||
'ssr.',
|
||||
)
|
||||
|
||||
debug?.(`using resolved config: %O`, {
|
||||
...resolved,
|
||||
plugins: resolved.plugins.map((p) => p.name),
|
||||
@ -1242,11 +1234,48 @@ export function isDepsOptimizerEnabled(
|
||||
config: ResolvedConfig,
|
||||
ssr: boolean,
|
||||
): boolean {
|
||||
const { command } = config
|
||||
const { disabled } = getDepOptimizationConfig(config, ssr)
|
||||
return !(
|
||||
disabled === true ||
|
||||
(command === 'build' && disabled === 'build') ||
|
||||
(command === 'serve' && disabled === 'dev')
|
||||
)
|
||||
const optimizeDeps = getDepOptimizationConfig(config, ssr)
|
||||
return !(optimizeDeps.noDiscovery && !optimizeDeps.include?.length)
|
||||
}
|
||||
|
||||
function optimizeDepsDisabledBackwardCompatibility(
|
||||
resolved: ResolvedConfig,
|
||||
optimizeDeps: DepOptimizationConfig,
|
||||
optimizeDepsPath: string = '',
|
||||
) {
|
||||
const optimizeDepsDisabled = optimizeDeps.disabled
|
||||
if (optimizeDepsDisabled !== undefined) {
|
||||
if (optimizeDepsDisabled === true || optimizeDepsDisabled === 'dev') {
|
||||
const commonjsOptionsInclude = resolved.build?.commonjsOptions?.include
|
||||
const commonjsPluginDisabled =
|
||||
Array.isArray(commonjsOptionsInclude) &&
|
||||
commonjsOptionsInclude.length === 0
|
||||
optimizeDeps.noDiscovery = true
|
||||
optimizeDeps.include = undefined
|
||||
if (commonjsPluginDisabled) {
|
||||
resolved.build.commonjsOptions.include = undefined
|
||||
}
|
||||
resolved.logger.warn(
|
||||
colors.yellow(`(!) Experimental ${optimizeDepsPath}optimizeDeps.disabled and deps pre-bundling during build were removed in Vite 5.1.
|
||||
To disable the deps optimizer, set ${optimizeDepsPath}optimizeDeps.noDiscovery to true and ${optimizeDepsPath}optimizeDeps.include as undefined or empty.
|
||||
Please remove ${optimizeDepsPath}optimizeDeps.disabled from your config.
|
||||
${
|
||||
commonjsPluginDisabled
|
||||
? 'Empty config.build.commonjsOptions.include will be ignored to support CJS during build. This config should also be removed.'
|
||||
: ''
|
||||
}
|
||||
`),
|
||||
)
|
||||
} else if (
|
||||
optimizeDepsDisabled === false ||
|
||||
optimizeDepsDisabled === 'build'
|
||||
) {
|
||||
resolved.logger.warn(
|
||||
colors.yellow(`(!) Experimental ${optimizeDepsPath}optimizeDeps.disabled and deps pre-bundling during build were removed in Vite 5.1.
|
||||
Setting it to ${optimizeDepsDisabled} now has no effect.
|
||||
Please remove ${optimizeDepsPath}optimizeDeps.disabled from your config.
|
||||
`),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,9 @@ import type { BuildContext, BuildOptions as EsbuildBuildOptions } from 'esbuild'
|
||||
import esbuild, { build } from 'esbuild'
|
||||
import { init, parse } from 'es-module-lexer'
|
||||
import glob from 'fast-glob'
|
||||
import { createFilter } from '@rollup/pluginutils'
|
||||
import { getDepOptimizationConfig } from '../config'
|
||||
import type { ResolvedConfig } from '../config'
|
||||
import {
|
||||
arraify,
|
||||
createDebugger,
|
||||
flattenId,
|
||||
getHash,
|
||||
@ -59,9 +57,6 @@ export interface DepsOptimizer {
|
||||
isOptimizedDepUrl: (url: string) => boolean
|
||||
getOptimizedDepId: (depInfo: OptimizedDepInfo) => string
|
||||
delayDepsOptimizerUntil: (id: string, done: () => Promise<any>) => void
|
||||
registerWorkersSource: (id: string) => void
|
||||
resetRegisteredIds: () => void
|
||||
ensureFirstRun: () => void
|
||||
|
||||
close: () => Promise<void>
|
||||
|
||||
@ -120,10 +115,12 @@ export interface DepOptimizationConfig {
|
||||
*/
|
||||
extensions?: string[]
|
||||
/**
|
||||
* Disables dependencies optimizations, true disables the optimizer during
|
||||
* build and dev. Pass 'build' or 'dev' to only disable the optimizer in
|
||||
* one of the modes. Deps optimization is enabled by default in dev only.
|
||||
* Deps optimization during build was removed in Vite 5.1. This option is
|
||||
* now redundant and will be removed in a future version. Switch to using
|
||||
* `optimizeDeps.noDiscovery` and an empty or undefined `optimizeDeps.include`.
|
||||
* true or 'dev' disables the optimizer, false or 'build' leaves it enabled.
|
||||
* @default 'build'
|
||||
* @deprecated
|
||||
* @experimental
|
||||
*/
|
||||
disabled?: boolean | 'build' | 'dev'
|
||||
@ -236,8 +233,7 @@ export async function optimizeDeps(
|
||||
asCommand = false,
|
||||
): Promise<DepOptimizationMetadata> {
|
||||
const log = asCommand ? config.logger.info : debug
|
||||
|
||||
const ssr = config.command === 'build' && !!config.build.ssr
|
||||
const ssr = false
|
||||
|
||||
const cachedMetadata = await loadCachedDepOptimizationMetadata(
|
||||
config,
|
||||
@ -258,7 +254,7 @@ export async function optimizeDeps(
|
||||
|
||||
const depsInfo = toDiscoveredDependencies(config, deps, ssr)
|
||||
|
||||
const result = await runOptimizeDeps(config, depsInfo).result
|
||||
const result = await runOptimizeDeps(config, depsInfo, ssr).result
|
||||
|
||||
await result.commit()
|
||||
|
||||
@ -279,37 +275,13 @@ export async function optimizeServerSsrDeps(
|
||||
return cachedMetadata
|
||||
}
|
||||
|
||||
let alsoInclude: string[] | undefined
|
||||
let noExternalFilter: ((id: unknown) => boolean) | undefined
|
||||
|
||||
const { exclude } = getDepOptimizationConfig(config, ssr)
|
||||
|
||||
const noExternal = config.ssr?.noExternal
|
||||
if (noExternal) {
|
||||
alsoInclude = arraify(noExternal).filter(
|
||||
(ne) => typeof ne === 'string',
|
||||
) as string[]
|
||||
noExternalFilter =
|
||||
noExternal === true
|
||||
? (dep: unknown) => true
|
||||
: createFilter(undefined, exclude, {
|
||||
resolve: false,
|
||||
})
|
||||
}
|
||||
|
||||
const deps: Record<string, string> = {}
|
||||
|
||||
await addManuallyIncludedOptimizeDeps(
|
||||
deps,
|
||||
config,
|
||||
ssr,
|
||||
alsoInclude,
|
||||
noExternalFilter,
|
||||
)
|
||||
await addManuallyIncludedOptimizeDeps(deps, config, ssr)
|
||||
|
||||
const depsInfo = toDiscoveredDependencies(config, deps, true)
|
||||
const depsInfo = toDiscoveredDependencies(config, deps, ssr)
|
||||
|
||||
const result = await runOptimizeDeps(config, depsInfo, true).result
|
||||
const result = await runOptimizeDeps(config, depsInfo, ssr).result
|
||||
|
||||
await result.commit()
|
||||
|
||||
@ -469,8 +441,7 @@ export function depsLogString(qualifiedIds: string[]): string {
|
||||
export function runOptimizeDeps(
|
||||
resolvedConfig: ResolvedConfig,
|
||||
depsInfo: Record<string, OptimizedDepInfo>,
|
||||
ssr: boolean = resolvedConfig.command === 'build' &&
|
||||
!!resolvedConfig.build.ssr,
|
||||
ssr: boolean,
|
||||
): {
|
||||
cancel: () => Promise<void>
|
||||
result: Promise<DepOptimizationResult>
|
||||
@ -733,7 +704,6 @@ async function prepareEsbuildOptimizerRun(
|
||||
context?: BuildContext
|
||||
idToExports: Record<string, ExportsData>
|
||||
}> {
|
||||
const isBuild = resolvedConfig.command === 'build'
|
||||
const config: ResolvedConfig = {
|
||||
...resolvedConfig,
|
||||
command: 'build',
|
||||
@ -774,13 +744,8 @@ async function prepareEsbuildOptimizerRun(
|
||||
|
||||
if (optimizerContext.cancelled) return { context: undefined, idToExports }
|
||||
|
||||
// esbuild automatically replaces process.env.NODE_ENV for platform 'browser'
|
||||
// But in lib mode, we need to keep process.env.NODE_ENV untouched
|
||||
const define = {
|
||||
'process.env.NODE_ENV':
|
||||
isBuild && config.build.lib
|
||||
? 'process.env.NODE_ENV'
|
||||
: JSON.stringify(process.env.NODE_ENV || config.mode),
|
||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || config.mode),
|
||||
}
|
||||
|
||||
const platform =
|
||||
@ -788,26 +753,6 @@ async function prepareEsbuildOptimizerRun(
|
||||
|
||||
const external = [...(optimizeDeps?.exclude ?? [])]
|
||||
|
||||
if (isBuild) {
|
||||
let rollupOptionsExternal = config?.build?.rollupOptions?.external
|
||||
if (rollupOptionsExternal) {
|
||||
if (typeof rollupOptionsExternal === 'string') {
|
||||
rollupOptionsExternal = [rollupOptionsExternal]
|
||||
}
|
||||
// TODO: decide whether to support RegExp and function options
|
||||
// They're not supported yet because `optimizeDeps.exclude` currently only accepts strings
|
||||
if (
|
||||
!Array.isArray(rollupOptionsExternal) ||
|
||||
rollupOptionsExternal.some((ext) => typeof ext !== 'string')
|
||||
) {
|
||||
throw new Error(
|
||||
`[vite] 'build.rollupOptions.external' can only be an array of strings or a string when using esbuild optimization at build time.`,
|
||||
)
|
||||
}
|
||||
external.push(...(rollupOptionsExternal as string[]))
|
||||
}
|
||||
}
|
||||
|
||||
const plugins = [...pluginsFromConfig]
|
||||
if (external.length) {
|
||||
plugins.push(esbuildCjsExternalPlugin(external, platform))
|
||||
@ -831,13 +776,13 @@ async function prepareEsbuildOptimizerRun(
|
||||
js: `import { createRequire } from 'module';const require = createRequire(import.meta.url);`,
|
||||
}
|
||||
: undefined,
|
||||
target: isBuild ? config.build.target || undefined : ESBUILD_MODULES_TARGET,
|
||||
target: ESBUILD_MODULES_TARGET,
|
||||
external,
|
||||
logLevel: 'error',
|
||||
splitting: true,
|
||||
sourcemap: true,
|
||||
outdir: processingCacheDir,
|
||||
ignoreAnnotations: !isBuild,
|
||||
ignoreAnnotations: true,
|
||||
metafile: true,
|
||||
plugins,
|
||||
charset: 'utf8',
|
||||
@ -855,13 +800,11 @@ export async function addManuallyIncludedOptimizeDeps(
|
||||
deps: Record<string, string>,
|
||||
config: ResolvedConfig,
|
||||
ssr: boolean,
|
||||
extra: string[] = [],
|
||||
filter?: (id: string) => boolean,
|
||||
): Promise<void> {
|
||||
const { logger } = config
|
||||
const optimizeDeps = getDepOptimizationConfig(config, ssr)
|
||||
const optimizeDepsInclude = optimizeDeps?.include ?? []
|
||||
if (optimizeDepsInclude.length || extra.length) {
|
||||
if (optimizeDepsInclude.length) {
|
||||
const unableToOptimize = (id: string, msg: string) => {
|
||||
if (optimizeDepsInclude.includes(id)) {
|
||||
logger.warn(
|
||||
@ -872,7 +815,7 @@ export async function addManuallyIncludedOptimizeDeps(
|
||||
}
|
||||
}
|
||||
|
||||
const includes = [...optimizeDepsInclude, ...extra]
|
||||
const includes = [...optimizeDepsInclude]
|
||||
for (let i = 0; i < includes.length; i++) {
|
||||
const id = includes[i]
|
||||
if (glob.isDynamicPattern(id)) {
|
||||
@ -887,7 +830,7 @@ export async function addManuallyIncludedOptimizeDeps(
|
||||
// normalize 'foo >bar` as 'foo > bar' to prevent same id being added
|
||||
// and for pretty printing
|
||||
const normalizedId = normalizeId(id)
|
||||
if (!deps[normalizedId] && filter?.(normalizedId) !== false) {
|
||||
if (!deps[normalizedId]) {
|
||||
const entry = await resolve(id)
|
||||
if (entry) {
|
||||
if (isOptimizable(entry, optimizeDeps)) {
|
||||
@ -926,30 +869,17 @@ export function getOptimizedDepPath(
|
||||
)
|
||||
}
|
||||
|
||||
function getDepsCacheSuffix(config: ResolvedConfig, ssr: boolean): string {
|
||||
let suffix = ''
|
||||
if (config.command === 'build') {
|
||||
// Differentiate build caches depending on outDir to allow parallel builds
|
||||
const { outDir } = config.build
|
||||
const buildId =
|
||||
outDir.length > 8 || outDir.includes('/') ? getHash(outDir) : outDir
|
||||
suffix += `_build-${buildId}`
|
||||
}
|
||||
if (ssr) {
|
||||
suffix += '_ssr'
|
||||
}
|
||||
return suffix
|
||||
function getDepsCacheSuffix(ssr: boolean): string {
|
||||
return ssr ? '_ssr' : ''
|
||||
}
|
||||
|
||||
export function getDepsCacheDir(config: ResolvedConfig, ssr: boolean): string {
|
||||
return getDepsCacheDirPrefix(config) + getDepsCacheSuffix(config, ssr)
|
||||
return getDepsCacheDirPrefix(config) + getDepsCacheSuffix(ssr)
|
||||
}
|
||||
|
||||
function getProcessingDepsCacheDir(config: ResolvedConfig, ssr: boolean) {
|
||||
return (
|
||||
getDepsCacheDirPrefix(config) +
|
||||
getDepsCacheSuffix(config, ssr) +
|
||||
getTempSuffix()
|
||||
getDepsCacheDirPrefix(config) + getDepsCacheSuffix(ssr) + getTempSuffix()
|
||||
)
|
||||
}
|
||||
|
||||
@ -1224,7 +1154,6 @@ function getConfigHash(config: ResolvedConfig, ssr: boolean): string {
|
||||
mode: process.env.NODE_ENV || config.mode,
|
||||
root: config.root,
|
||||
resolve: config.resolve,
|
||||
buildTarget: config.build.target,
|
||||
assetsInclude: config.assetsInclude,
|
||||
plugins: config.plugins.map((p) => p.name),
|
||||
optimizeDeps: {
|
||||
|
@ -36,20 +36,14 @@ export function getDepsOptimizer(
|
||||
config: ResolvedConfig,
|
||||
ssr?: boolean,
|
||||
): DepsOptimizer | undefined {
|
||||
// Workers compilation shares the DepsOptimizer from the main build
|
||||
const isDevSsr = ssr && config.command !== 'build'
|
||||
return (isDevSsr ? devSsrDepsOptimizerMap : depsOptimizerMap).get(
|
||||
config.mainConfig || config,
|
||||
)
|
||||
return (ssr ? devSsrDepsOptimizerMap : depsOptimizerMap).get(config)
|
||||
}
|
||||
|
||||
export async function initDepsOptimizer(
|
||||
config: ResolvedConfig,
|
||||
server?: ViteDevServer,
|
||||
): Promise<void> {
|
||||
// Non Dev SSR Optimizer
|
||||
const ssr = config.command === 'build' && !!config.build.ssr
|
||||
if (!getDepsOptimizer(config, ssr)) {
|
||||
if (!getDepsOptimizer(config, false)) {
|
||||
await createDepsOptimizer(config, server)
|
||||
}
|
||||
}
|
||||
@ -87,9 +81,7 @@ async function createDepsOptimizer(
|
||||
server?: ViteDevServer,
|
||||
): Promise<void> {
|
||||
const { logger } = config
|
||||
const isBuild = config.command === 'build'
|
||||
const ssr = isBuild && !!config.build.ssr // safe as Dev SSR don't use this optimizer
|
||||
|
||||
const ssr = false
|
||||
const sessionTimestamp = Date.now().toString()
|
||||
|
||||
const cachedMetadata = await loadCachedDepOptimizationMetadata(config, ssr)
|
||||
@ -108,11 +100,8 @@ async function createDepsOptimizer(
|
||||
isOptimizedDepFile: createIsOptimizedDepFile(config),
|
||||
isOptimizedDepUrl: createIsOptimizedDepUrl(config),
|
||||
getOptimizedDepId: (depInfo: OptimizedDepInfo) =>
|
||||
isBuild ? depInfo.file : `${depInfo.file}?v=${depInfo.browserHash}`,
|
||||
registerWorkersSource,
|
||||
`${depInfo.file}?v=${depInfo.browserHash}`,
|
||||
delayDepsOptimizerUntil,
|
||||
resetRegisteredIds,
|
||||
ensureFirstRun,
|
||||
close,
|
||||
options: getDepOptimizationConfig(config, ssr),
|
||||
}
|
||||
@ -152,15 +141,12 @@ async function createDepsOptimizer(
|
||||
|
||||
let firstRunCalled = !!cachedMetadata
|
||||
|
||||
// During build, we wait for every module to be scanned before resolving
|
||||
// optimized deps loading for rollup on each rebuild. It will be recreated
|
||||
// after each buildStart.
|
||||
// During dev, if this is a cold run, we wait for static imports discovered
|
||||
// If this is a cold run, we wait for static imports discovered
|
||||
// from the first request before resolving to minimize full page reloads.
|
||||
// On warm start or after the first optimization is run, we use a simpler
|
||||
// debounce strategy each time a new dep is discovered.
|
||||
let crawlEndFinder: CrawlEndFinder | undefined
|
||||
if (isBuild || !cachedMetadata) {
|
||||
if (!cachedMetadata) {
|
||||
crawlEndFinder = setupOnCrawlEnd(onCrawlEnd)
|
||||
}
|
||||
|
||||
@ -216,7 +202,7 @@ async function createDepsOptimizer(
|
||||
// We don't need to scan for dependencies or wait for the static crawl to end
|
||||
// Run the first optimization run immediately
|
||||
runOptimizer()
|
||||
} else if (!isBuild) {
|
||||
} else {
|
||||
// Important, the scanner is dev only
|
||||
depsOptimizer.scanProcessing = new Promise((resolve) => {
|
||||
// Runs in the background in case blocking high priority tasks
|
||||
@ -243,7 +229,7 @@ async function createDepsOptimizer(
|
||||
// run on the background, but we wait until crawling has ended
|
||||
// to decide if we send this result to the browser or we need to
|
||||
// do another optimize step
|
||||
optimizationResult = runOptimizeDeps(config, knownDeps)
|
||||
optimizationResult = runOptimizeDeps(config, knownDeps, ssr)
|
||||
} catch (e) {
|
||||
logger.error(e.stack || e.message)
|
||||
} finally {
|
||||
@ -318,7 +304,7 @@ async function createDepsOptimizer(
|
||||
const knownDeps = prepareKnownDeps()
|
||||
startNextDiscoveredBatch()
|
||||
|
||||
optimizationResult = runOptimizeDeps(config, knownDeps)
|
||||
optimizationResult = runOptimizeDeps(config, knownDeps, ssr)
|
||||
processingResult = await optimizationResult.result
|
||||
optimizationResult = undefined
|
||||
}
|
||||
@ -541,11 +527,6 @@ async function createDepsOptimizer(
|
||||
// browser a dependency that may be outdated, thus avoiding full page reloads
|
||||
|
||||
if (!crawlEndFinder) {
|
||||
if (isBuild) {
|
||||
logger.error(
|
||||
'Vite Internal Error: Missing dependency found after crawling ended',
|
||||
)
|
||||
}
|
||||
// Debounced rerun, let other missing dependencies be discovered before
|
||||
// the running next optimizeDeps
|
||||
debouncedProcessing()
|
||||
@ -595,15 +576,11 @@ async function createDepsOptimizer(
|
||||
}, timeout)
|
||||
}
|
||||
|
||||
// During dev, onCrawlEnd is called once when the server starts and all static
|
||||
// onCrawlEnd is called once when the server starts and all static
|
||||
// imports after the first request have been crawled (dynamic imports may also
|
||||
// be crawled if the browser requests them right away).
|
||||
// During build, onCrawlEnd will be called once after each buildStart (so in
|
||||
// watch mode it will be called after each rebuild has processed every module).
|
||||
// All modules are transformed first in this case (both static and dynamic).
|
||||
async function onCrawlEnd() {
|
||||
// On build time, a missing dep appearing after onCrawlEnd is an internal error
|
||||
// On dev, switch after this point to a simple debounce strategy
|
||||
// switch after this point to a simple debounce strategy
|
||||
crawlEndFinder = undefined
|
||||
|
||||
debug?.(colors.green(`✨ static imports crawl ended`))
|
||||
@ -615,7 +592,7 @@ async function createDepsOptimizer(
|
||||
// It normally should be over by the time crawling of user code ended
|
||||
await depsOptimizer.scanProcessing
|
||||
|
||||
if (!isBuild && optimizationResult && !config.optimizeDeps.noDiscovery) {
|
||||
if (optimizationResult && !config.optimizeDeps.noDiscovery) {
|
||||
const result = await optimizationResult.result
|
||||
optimizationResult = undefined
|
||||
currentlyProcessing = false
|
||||
@ -690,30 +667,16 @@ async function createDepsOptimizer(
|
||||
}
|
||||
}
|
||||
|
||||
// Called during buildStart at build time, when build --watch is used.
|
||||
function resetRegisteredIds() {
|
||||
crawlEndFinder?.cancel()
|
||||
crawlEndFinder = setupOnCrawlEnd(onCrawlEnd)
|
||||
}
|
||||
|
||||
function registerWorkersSource(id: string) {
|
||||
crawlEndFinder?.registerWorkersSource(id)
|
||||
}
|
||||
function delayDepsOptimizerUntil(id: string, done: () => Promise<any>) {
|
||||
if (crawlEndFinder && !depsOptimizer.isOptimizedDepFile(id)) {
|
||||
crawlEndFinder.delayDepsOptimizerUntil(id, done)
|
||||
}
|
||||
}
|
||||
function ensureFirstRun() {
|
||||
crawlEndFinder?.ensureFirstRun()
|
||||
}
|
||||
}
|
||||
|
||||
const callCrawlEndIfIdleAfterMs = 50
|
||||
|
||||
interface CrawlEndFinder {
|
||||
ensureFirstRun: () => void
|
||||
registerWorkersSource: (id: string) => void
|
||||
delayDepsOptimizerUntil: (id: string, done: () => Promise<any>) => void
|
||||
cancel: () => void
|
||||
}
|
||||
@ -721,7 +684,6 @@ interface CrawlEndFinder {
|
||||
function setupOnCrawlEnd(onCrawlEnd: () => void): CrawlEndFinder {
|
||||
const registeredIds = new Set<string>()
|
||||
const seenIds = new Set<string>()
|
||||
const workersSources = new Set<string>()
|
||||
let timeoutHandle: NodeJS.Timeout | undefined
|
||||
|
||||
let cancelled = false
|
||||
@ -737,40 +699,13 @@ function setupOnCrawlEnd(onCrawlEnd: () => void): CrawlEndFinder {
|
||||
}
|
||||
}
|
||||
|
||||
// If all the inputs are dependencies, we aren't going to get any
|
||||
// delayDepsOptimizerUntil(id) calls. We need to guard against this
|
||||
// by forcing a rerun if no deps have been registered
|
||||
let firstRunEnsured = false
|
||||
function ensureFirstRun() {
|
||||
if (!firstRunEnsured && seenIds.size === 0) {
|
||||
setTimeout(() => {
|
||||
if (seenIds.size === 0) {
|
||||
callOnCrawlEnd()
|
||||
}
|
||||
}, 200)
|
||||
}
|
||||
firstRunEnsured = true
|
||||
}
|
||||
|
||||
function registerWorkersSource(id: string): void {
|
||||
workersSources.add(id)
|
||||
|
||||
// Avoid waiting for this id, as it may be blocked by the rollup
|
||||
// bundling process of the worker that also depends on the optimizer
|
||||
registeredIds.delete(id)
|
||||
|
||||
checkIfCrawlEndAfterTimeout()
|
||||
}
|
||||
|
||||
function delayDepsOptimizerUntil(id: string, done: () => Promise<any>): void {
|
||||
if (!seenIds.has(id)) {
|
||||
seenIds.add(id)
|
||||
if (!workersSources.has(id)) {
|
||||
registeredIds.add(id)
|
||||
done()
|
||||
.catch(() => {})
|
||||
.finally(() => markIdAsDone(id))
|
||||
}
|
||||
registeredIds.add(id)
|
||||
done()
|
||||
.catch(() => {})
|
||||
.finally(() => markIdAsDone(id))
|
||||
}
|
||||
}
|
||||
function markIdAsDone(id: string): void {
|
||||
@ -793,8 +728,6 @@ function setupOnCrawlEnd(onCrawlEnd: () => void): CrawlEndFinder {
|
||||
}
|
||||
|
||||
return {
|
||||
ensureFirstRun,
|
||||
registerWorkersSource,
|
||||
delayDepsOptimizerUntil,
|
||||
cancel,
|
||||
}
|
||||
@ -820,10 +753,7 @@ async function createDevSsrDepsOptimizer(
|
||||
// noop, there is no scanning during dev SSR
|
||||
// the optimizer blocks the server start
|
||||
run: () => {},
|
||||
registerWorkersSource: (id: string) => {},
|
||||
delayDepsOptimizerUntil: (id: string, done: () => Promise<any>) => {},
|
||||
resetRegisteredIds: () => {},
|
||||
ensureFirstRun: () => {},
|
||||
|
||||
close: async () => {},
|
||||
options: config.ssr.optimizeDeps,
|
||||
|
@ -6,28 +6,20 @@ import type {
|
||||
} from 'es-module-lexer'
|
||||
import { init, parse as parseImports } from 'es-module-lexer'
|
||||
import type { OutputChunk, SourceMap } from 'rollup'
|
||||
import colors from 'picocolors'
|
||||
import type { RawSourceMap } from '@ampproject/remapping'
|
||||
import convertSourceMap from 'convert-source-map'
|
||||
import {
|
||||
cleanUrl,
|
||||
combineSourcemaps,
|
||||
generateCodeFrame,
|
||||
isDataUrl,
|
||||
isExternalUrl,
|
||||
isInNodeModules,
|
||||
moduleListContains,
|
||||
numberToPos,
|
||||
withTrailingSlash,
|
||||
} from '../utils'
|
||||
import type { Plugin } from '../plugin'
|
||||
import { getDepOptimizationConfig } from '../config'
|
||||
import type { ResolvedConfig } from '../config'
|
||||
import { toOutputFilePathInJS } from '../build'
|
||||
import { genSourceMapUrl } from '../server/sourcemap'
|
||||
import { getDepsOptimizer, optimizedDepNeedsInterop } from '../optimizer'
|
||||
import { removedPureCssFilesCache } from './css'
|
||||
import { createParseErrorInfo, interopNamedImports } from './importAnalysis'
|
||||
import { createParseErrorInfo } from './importAnalysis'
|
||||
|
||||
type FileDep = {
|
||||
url: string
|
||||
@ -49,10 +41,6 @@ const preloadMarkerWithQuote = new RegExp(`['"]${preloadMarker}['"]`, 'g')
|
||||
|
||||
const dynamicImportPrefixRE = /import\s*\(/
|
||||
|
||||
// TODO: abstract
|
||||
const optimizedDepChunkRE = /\/chunk-[A-Z\d]{8}\.js/
|
||||
const optimizedDepDynamicRE = /-[A-Z\d]{8}\.js/
|
||||
|
||||
function toRelativePath(filename: string, importer: string) {
|
||||
const relPath = path.posix.relative(path.posix.dirname(importer), filename)
|
||||
return relPath[0] === '.' ? relPath : `./${relPath}`
|
||||
@ -237,78 +225,15 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
|
||||
return null
|
||||
}
|
||||
|
||||
const { root } = config
|
||||
const depsOptimizer = getDepsOptimizer(config, ssr)
|
||||
|
||||
const normalizeUrl = async (
|
||||
url: string,
|
||||
pos: number,
|
||||
): Promise<[string, string]> => {
|
||||
let importerFile = importer
|
||||
|
||||
const optimizeDeps = getDepOptimizationConfig(config, ssr)
|
||||
if (moduleListContains(optimizeDeps?.exclude, url)) {
|
||||
if (depsOptimizer) {
|
||||
await depsOptimizer.scanProcessing
|
||||
|
||||
// if the dependency encountered in the optimized file was excluded from the optimization
|
||||
// the dependency needs to be resolved starting from the original source location of the optimized file
|
||||
// because starting from node_modules/.vite will not find the dependency if it was not hoisted
|
||||
// (that is, if it is under node_modules directory in the package source of the optimized file)
|
||||
for (const optimizedModule of depsOptimizer.metadata.depInfoList) {
|
||||
if (!optimizedModule.src) continue // Ignore chunks
|
||||
if (optimizedModule.file === importer) {
|
||||
importerFile = optimizedModule.src
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const resolved = await this.resolve(url, importerFile, {
|
||||
skipSelf: false,
|
||||
})
|
||||
|
||||
if (!resolved) {
|
||||
// in ssr, we should let node handle the missing modules
|
||||
if (ssr) {
|
||||
return [url, url]
|
||||
}
|
||||
return this.error(
|
||||
`Failed to resolve import "${url}" from "${path.relative(
|
||||
process.cwd(),
|
||||
importerFile,
|
||||
)}". Does the file exist?`,
|
||||
pos,
|
||||
)
|
||||
}
|
||||
|
||||
// normalize all imports into resolved URLs
|
||||
// e.g. `import 'foo'` -> `import '/@fs/.../node_modules/foo/index.js'`
|
||||
if (resolved.id.startsWith(withTrailingSlash(root))) {
|
||||
// in root: infer short absolute path from root
|
||||
url = resolved.id.slice(root.length)
|
||||
} else {
|
||||
url = resolved.id
|
||||
}
|
||||
|
||||
if (isExternalUrl(url)) {
|
||||
return [url, url]
|
||||
}
|
||||
|
||||
return [url, resolved.id]
|
||||
}
|
||||
|
||||
let s: MagicString | undefined
|
||||
const str = () => s || (s = new MagicString(source))
|
||||
let needPreloadHelper = false
|
||||
|
||||
for (let index = 0; index < imports.length; index++) {
|
||||
const {
|
||||
s: start,
|
||||
e: end,
|
||||
ss: expStart,
|
||||
se: expEnd,
|
||||
n: specifier,
|
||||
d: dynamicIndex,
|
||||
a: attributeIndex,
|
||||
} = imports[index]
|
||||
@ -332,66 +257,6 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
|
||||
})`,
|
||||
)
|
||||
}
|
||||
|
||||
// static import or valid string in dynamic import
|
||||
// If resolvable, let's resolve it
|
||||
if (depsOptimizer && specifier) {
|
||||
// skip external / data uri
|
||||
if (isExternalUrl(specifier) || isDataUrl(specifier)) {
|
||||
continue
|
||||
}
|
||||
|
||||
// normalize
|
||||
const [url, resolvedId] = await normalizeUrl(specifier, start)
|
||||
|
||||
if (url !== specifier) {
|
||||
if (
|
||||
depsOptimizer.isOptimizedDepFile(resolvedId) &&
|
||||
!optimizedDepChunkRE.test(resolvedId)
|
||||
) {
|
||||
const file = cleanUrl(resolvedId) // Remove ?v={hash}
|
||||
|
||||
const needsInterop = await optimizedDepNeedsInterop(
|
||||
depsOptimizer.metadata,
|
||||
file,
|
||||
config,
|
||||
ssr,
|
||||
)
|
||||
|
||||
let rewriteDone = false
|
||||
|
||||
if (needsInterop === undefined) {
|
||||
// Non-entry dynamic imports from dependencies will reach here as there isn't
|
||||
// optimize info for them, but they don't need es interop. If the request isn't
|
||||
// a dynamic import, then it is an internal Vite error
|
||||
if (!optimizedDepDynamicRE.test(file)) {
|
||||
config.logger.error(
|
||||
colors.red(
|
||||
`Vite Error, ${url} optimized info should be defined`,
|
||||
),
|
||||
)
|
||||
}
|
||||
} else if (needsInterop) {
|
||||
// config.logger.info(`${url} needs interop`)
|
||||
interopNamedImports(
|
||||
str(),
|
||||
imports[index],
|
||||
url,
|
||||
index,
|
||||
importer,
|
||||
config,
|
||||
)
|
||||
rewriteDone = true
|
||||
}
|
||||
if (!rewriteDone) {
|
||||
const rewrittenUrl = JSON.stringify(file)
|
||||
const s = isDynamicImport ? start : start - 1
|
||||
const e = isDynamicImport ? end : end + 1
|
||||
str().update(s, e, rewrittenUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
|
@ -9,7 +9,7 @@ import { watchPackageDataPlugin } from '../packages'
|
||||
import { getFsUtils } from '../fsUtils'
|
||||
import { jsonPlugin } from './json'
|
||||
import { resolvePlugin } from './resolve'
|
||||
import { optimizedDepsBuildPlugin, optimizedDepsPlugin } from './optimizedDeps'
|
||||
import { optimizedDepsPlugin } from './optimizedDeps'
|
||||
import { esbuildPlugin } from './esbuild'
|
||||
import { importAnalysisPlugin } from './importAnalysis'
|
||||
import { cssPlugin, cssPostPlugin } from './css'
|
||||
@ -39,16 +39,12 @@ export async function resolvePlugins(
|
||||
? await (await import('../build')).resolveBuildPlugins(config)
|
||||
: { pre: [], post: [] }
|
||||
const { modulePreload } = config.build
|
||||
|
||||
const depsOptimizerEnabled =
|
||||
!isBuild &&
|
||||
(isDepsOptimizerEnabled(config, false) ||
|
||||
isDepsOptimizerEnabled(config, true))
|
||||
return [
|
||||
...(isDepsOptimizerEnabled(config, false) ||
|
||||
isDepsOptimizerEnabled(config, true)
|
||||
? [
|
||||
isBuild
|
||||
? optimizedDepsBuildPlugin(config)
|
||||
: optimizedDepsPlugin(config),
|
||||
]
|
||||
: []),
|
||||
depsOptimizerEnabled ? optimizedDepsPlugin(config) : null,
|
||||
isBuild ? metadataPlugin() : null,
|
||||
!isWorker ? watchPackageDataPlugin(config.packageCache) : null,
|
||||
preAliasPlugin(config),
|
||||
@ -69,7 +65,9 @@ export async function resolvePlugins(
|
||||
ssrConfig: config.ssr,
|
||||
asSrc: true,
|
||||
fsUtils: getFsUtils(config),
|
||||
getDepsOptimizer: (ssr: boolean) => getDepsOptimizer(config, ssr),
|
||||
getDepsOptimizer: isBuild
|
||||
? undefined
|
||||
: (ssr: boolean) => getDepsOptimizer(config, ssr),
|
||||
shouldExternalize:
|
||||
isBuild && config.build.ssr
|
||||
? (id, importer) => shouldExternalizeForSSR(id, importer, config)
|
||||
|
@ -75,71 +75,6 @@ export function optimizedDepsPlugin(config: ResolvedConfig): Plugin {
|
||||
}
|
||||
}
|
||||
|
||||
export function optimizedDepsBuildPlugin(config: ResolvedConfig): Plugin {
|
||||
let buildStartCalled = false
|
||||
|
||||
return {
|
||||
name: 'vite:optimized-deps-build',
|
||||
|
||||
buildStart() {
|
||||
// Only reset the registered ids after a rebuild during build --watch
|
||||
if (!config.isWorker && buildStartCalled) {
|
||||
getDepsOptimizer(config)?.resetRegisteredIds()
|
||||
}
|
||||
buildStartCalled = true
|
||||
},
|
||||
|
||||
async resolveId(id, importer, options) {
|
||||
const depsOptimizer = getDepsOptimizer(config)
|
||||
if (!depsOptimizer) return
|
||||
|
||||
if (depsOptimizer.isOptimizedDepFile(id)) {
|
||||
return id
|
||||
} else {
|
||||
if (options?.custom?.['vite:pre-alias']) {
|
||||
// Skip registering the id if it is being resolved from the pre-alias plugin
|
||||
// When a optimized dep is aliased, we need to avoid waiting for it before optimizing
|
||||
return
|
||||
}
|
||||
const resolved = await this.resolve(id, importer, options)
|
||||
if (resolved && !resolved.external) {
|
||||
depsOptimizer.delayDepsOptimizerUntil(resolved.id, async () => {
|
||||
await this.load(resolved)
|
||||
})
|
||||
}
|
||||
return resolved
|
||||
}
|
||||
},
|
||||
|
||||
async load(id) {
|
||||
const depsOptimizer = getDepsOptimizer(config)
|
||||
if (!depsOptimizer?.isOptimizedDepFile(id)) {
|
||||
return
|
||||
}
|
||||
|
||||
depsOptimizer?.ensureFirstRun()
|
||||
|
||||
const file = cleanUrl(id)
|
||||
// Search in both the currently optimized and newly discovered deps
|
||||
// If all the inputs are dependencies, we aren't going to get any
|
||||
const info = optimizedDepInfoFromFile(depsOptimizer.metadata, file)
|
||||
if (info) {
|
||||
await info.processing
|
||||
debug?.(`load ${colors.cyan(file)}`)
|
||||
} else {
|
||||
throw new Error(
|
||||
`Something unexpected happened while optimizing "${id}".`,
|
||||
)
|
||||
}
|
||||
|
||||
// Load the file from the cache instead of waiting for other plugin
|
||||
// load hooks to avoid race conditions, once processing is resolved,
|
||||
// we are sure that the file has been properly save to disk
|
||||
return fsp.readFile(file, 'utf-8')
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function throwProcessingError(id: string): never {
|
||||
const err: any = new Error(
|
||||
`Something unexpected happened while optimizing "${id}". ` +
|
||||
|
@ -31,7 +31,7 @@ export function preAliasPlugin(config: ResolvedConfig): Plugin {
|
||||
name: 'vite:pre-alias',
|
||||
async resolveId(id, importer, options) {
|
||||
const ssr = options?.ssr === true
|
||||
const depsOptimizer = getDepsOptimizer(config, ssr)
|
||||
const depsOptimizer = !isBuild && getDepsOptimizer(config, ssr)
|
||||
if (
|
||||
importer &&
|
||||
depsOptimizer &&
|
||||
|
@ -837,7 +837,7 @@ export function tryNodeResolve(
|
||||
}
|
||||
|
||||
const skipOptimization =
|
||||
depsOptimizer?.options.noDiscovery ||
|
||||
(!options.ssrOptimizeCheck && depsOptimizer?.options.noDiscovery) ||
|
||||
!isJsType ||
|
||||
(importer && isInNodeModules(importer)) ||
|
||||
exclude?.includes(pkgId) ||
|
||||
|
@ -11,7 +11,6 @@ import {
|
||||
onRollupWarning,
|
||||
toOutputFilePathInJS,
|
||||
} from '../build'
|
||||
import { getDepsOptimizer } from '../optimizer'
|
||||
import { fileToUrl } from './asset'
|
||||
|
||||
interface WorkerCache {
|
||||
@ -235,7 +234,6 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
|
||||
},
|
||||
|
||||
async transform(raw, id, options) {
|
||||
const ssr = options?.ssr === true
|
||||
const query = parseRequest(id)
|
||||
if (query && query[WORKER_FILE_ID] != null) {
|
||||
// if import worker by worker constructor will have query.type
|
||||
@ -295,7 +293,6 @@ export function webWorkerPlugin(config: ResolvedConfig): Plugin {
|
||||
}`
|
||||
|
||||
if (isBuild) {
|
||||
getDepsOptimizer(config, ssr)?.registerWorkersSource(id)
|
||||
if (query.inline != null) {
|
||||
const chunk = await bundleWorkerEntry(config, id, query)
|
||||
const encodedJs = `const encodedJs = "${Buffer.from(
|
||||
|
@ -12,7 +12,6 @@ import {
|
||||
slash,
|
||||
transformStableResult,
|
||||
} from '../utils'
|
||||
import { getDepsOptimizer } from '../optimizer'
|
||||
import type { ResolveFn } from '..'
|
||||
import type { WorkerType } from './worker'
|
||||
import { WORKER_FILE_ID, workerFileToUrl } from './worker'
|
||||
@ -131,7 +130,6 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
|
||||
},
|
||||
|
||||
async transform(code, id, options) {
|
||||
const ssr = options?.ssr === true
|
||||
if (!options?.ssr && isIncludeWorkerImportMetaUrl(code)) {
|
||||
const query = parseRequest(id)
|
||||
let s: MagicString | undefined
|
||||
@ -176,7 +174,6 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
|
||||
|
||||
let builtUrl: string
|
||||
if (isBuild) {
|
||||
getDepsOptimizer(config, ssr)?.registerWorkersSource(id)
|
||||
builtUrl = await workerFileToUrl(config, file, query)
|
||||
} else {
|
||||
builtUrl = await fileToUrl(cleanUrl(file), config, this)
|
||||
|
@ -12,7 +12,7 @@ async function createDevServer() {
|
||||
root,
|
||||
logLevel: 'silent',
|
||||
optimizeDeps: {
|
||||
disabled: true,
|
||||
noDiscovery: true,
|
||||
},
|
||||
})
|
||||
server.pluginContainer.buildStart({})
|
||||
|
@ -10,7 +10,7 @@ async function createDevServer() {
|
||||
root,
|
||||
logLevel: 'silent',
|
||||
optimizeDeps: {
|
||||
disabled: true,
|
||||
noDiscovery: true,
|
||||
},
|
||||
})
|
||||
server.pluginContainer.buildStart({})
|
||||
|
@ -60,8 +60,8 @@ export function resolveSSROptions(
|
||||
target,
|
||||
...ssr,
|
||||
optimizeDeps: {
|
||||
disabled: true,
|
||||
...optimizeDeps,
|
||||
noDiscovery: true, // always true for ssr
|
||||
esbuildOptions: {
|
||||
preserveSymlinks,
|
||||
...optimizeDeps.esbuildOptions,
|
||||
|
@ -5,7 +5,6 @@ process.env.NODE_ENV = ''
|
||||
|
||||
export default defineConfig({
|
||||
optimizeDeps: {
|
||||
disabled: false,
|
||||
noDiscovery: true,
|
||||
include: ['@vitejs/test-dep-no-discovery'],
|
||||
},
|
||||
@ -13,9 +12,5 @@ export default defineConfig({
|
||||
build: {
|
||||
// to make tests faster
|
||||
minify: false,
|
||||
// Avoid @rollup/plugin-commonjs
|
||||
commonjsOptions: {
|
||||
include: [],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
@ -172,7 +172,7 @@ test('vue + vuex', async () => {
|
||||
|
||||
// When we use the Rollup CommonJS plugin instead of esbuild prebundling,
|
||||
// the esbuild plugins won't apply to dependencies
|
||||
test('esbuild-plugin', async () => {
|
||||
test.runIf(isServe)('esbuild-plugin', async () => {
|
||||
await expectWithRetry(() => page.textContent('.esbuild-plugin')).toMatch(
|
||||
`Hello from an esbuild plugin`,
|
||||
)
|
||||
|
@ -17,7 +17,6 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
optimizeDeps: {
|
||||
disabled: false,
|
||||
include: [
|
||||
'@vitejs/test-dep-linked-include',
|
||||
'@vitejs/test-nested-exclude > @vitejs/test-nested-include',
|
||||
@ -49,10 +48,6 @@ export default defineConfig({
|
||||
build: {
|
||||
// to make tests faster
|
||||
minify: false,
|
||||
// Avoid @rollup/plugin-commonjs
|
||||
commonjsOptions: {
|
||||
include: [],
|
||||
},
|
||||
rollupOptions: {
|
||||
onwarn(msg, warn) {
|
||||
// filter `"Buffer" is not exported by "__vite-browser-external"` warning
|
||||
|
@ -8,6 +8,13 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
const isTest = process.env.VITEST
|
||||
|
||||
const noExternal = [
|
||||
'@vitejs/test-no-external-cjs',
|
||||
'@vitejs/test-import-builtin-cjs',
|
||||
'@vitejs/test-no-external-css',
|
||||
'@vitejs/test-external-entry',
|
||||
]
|
||||
|
||||
export async function createServer(root = process.cwd(), hmrPort) {
|
||||
const resolve = (p) => path.resolve(__dirname, p)
|
||||
|
||||
@ -35,18 +42,13 @@ export async function createServer(root = process.cwd(), hmrPort) {
|
||||
},
|
||||
appType: 'custom',
|
||||
ssr: {
|
||||
noExternal: [
|
||||
'@vitejs/test-no-external-cjs',
|
||||
'@vitejs/test-import-builtin-cjs',
|
||||
'@vitejs/test-no-external-css',
|
||||
'@vitejs/test-external-entry',
|
||||
],
|
||||
noExternal,
|
||||
external: [
|
||||
'@vitejs/test-nested-external',
|
||||
'@vitejs/test-external-entry/entry',
|
||||
],
|
||||
optimizeDeps: {
|
||||
disabled: 'build',
|
||||
include: noExternal,
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { expect, test } from 'vitest'
|
||||
import { port } from './serve'
|
||||
import { page } from '~utils'
|
||||
import { isBuild, page } from '~utils'
|
||||
|
||||
const url = `http://localhost:${port}`
|
||||
|
||||
test('message from require-external-cjs', async () => {
|
||||
test.runIf(!isBuild)('message from require-external-cjs', async () => {
|
||||
await page.goto(url)
|
||||
expect(await page.textContent('.require-external-cjs')).toMatch('foo')
|
||||
})
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { defineConfig } from 'vite'
|
||||
|
||||
const noExternal = ['@vitejs/test-require-external-cjs']
|
||||
export default defineConfig({
|
||||
ssr: {
|
||||
noExternal: ['@vitejs/test-require-external-cjs'],
|
||||
noExternal,
|
||||
external: ['@vitejs/test-external-cjs'],
|
||||
optimizeDeps: {
|
||||
disabled: false,
|
||||
include: noExternal,
|
||||
},
|
||||
},
|
||||
build: {
|
||||
@ -14,8 +15,5 @@ export default defineConfig({
|
||||
rollupOptions: {
|
||||
external: ['@vitejs/test-external-cjs'],
|
||||
},
|
||||
commonjsOptions: {
|
||||
include: [],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user