Skip to content

Commit

Permalink
refactor: introduce mergeWithDefaults and organize how default valu…
Browse files Browse the repository at this point in the history
…es for config options are set (#18550)
  • Loading branch information
sapphi-red authored Nov 12, 2024
1 parent 584a573 commit 0e1f437
Show file tree
Hide file tree
Showing 12 changed files with 571 additions and 226 deletions.
50 changes: 50 additions & 0 deletions packages/vite/src/node/__tests__/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
getLocalhostAddressIfDiffersFromDNS,
injectQuery,
isFileReadable,
mergeWithDefaults,
posToNumber,
processSrcSetSync,
resolveHostname,
Expand Down Expand Up @@ -449,3 +450,52 @@ describe('flattenId', () => {
expect(result2).toHaveLength(170)
})
})

describe('mergeWithDefaults', () => {
test('merges with defaults', () => {
const actual = mergeWithDefaults(
{
useDefault: 1,
useValueIfNull: 2,
replaceArray: [0, 1],
nested: {
foo: 'bar',
},
},
{
useDefault: undefined,
useValueIfNull: null,
useValueIfNoDefault: 'foo',
replaceArray: [2, 3],
nested: {
foo2: 'bar2',
},
},
)
expect(actual).toStrictEqual({
useDefault: 1,
useValueIfNull: null,
useValueIfNoDefault: 'foo',
replaceArray: [2, 3],
nested: {
foo: 'bar',
foo2: 'bar2',
},
})

const defaults = {
object: {},
array: [],
regex: /foo/,
function: () => {},
}
const actual2 = mergeWithDefaults(defaults, {})
expect(actual2.object).toStrictEqual({})
expect(actual2.array).toStrictEqual([])
expect(actual2.regex).toStrictEqual(/foo/)
expect(actual2.function).toStrictEqual(expect.any(Function))
// cloned
expect(actual2.object).not.toBe(defaults.object)
expect(actual2.array).not.toBe(defaults.array)
})
})
58 changes: 58 additions & 0 deletions packages/vite/src/node/__tests_dts__/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import type { Equal, ExpectTrue } from '@type-challenges/utils'
import { mergeWithDefaults } from '../utils'

const useDefaultTypeForUndefined1 = mergeWithDefaults(
{
foo: 1,
},
{},
)

const useDefaultTypeForUndefined2 = mergeWithDefaults(
{
foo: 1,
},
{
foo: 2 as number | undefined,
},
)

const includeKeyNotIncludedInDefault1 = mergeWithDefaults(
{},
{
foo: 2,
},
)

const extendTypeWithValueType = mergeWithDefaults(
{
foo: 1,
},
{
foo: 'string' as string | number,
},
)

const plainObject = mergeWithDefaults({ foo: { bar: 1 } }, { foo: { baz: 2 } })

const nonPlainObject = mergeWithDefaults(
{ foo: ['foo'] },
{ foo: [0] as number[] | undefined },
)

const optionalNested = mergeWithDefaults({ foo: { bar: true } }, {
foo: { bar: false },
} as { foo?: { bar?: boolean } })

export type cases1 = [
ExpectTrue<Equal<typeof useDefaultTypeForUndefined1, { foo: number }>>,
ExpectTrue<Equal<typeof useDefaultTypeForUndefined2, { foo: number }>>,
ExpectTrue<Equal<typeof includeKeyNotIncludedInDefault1, { foo: number }>>,
ExpectTrue<Equal<typeof extendTypeWithValueType, { foo: string | number }>>,
ExpectTrue<Equal<typeof plainObject, { foo: { bar: number; baz: number } }>>,
ExpectTrue<Equal<typeof nonPlainObject, { foo: string[] | number[] }>>,
ExpectTrue<
Equal<typeof optionalNested, { foo: { bar: boolean } | { bar: boolean } }>
>,
]
155 changes: 82 additions & 73 deletions packages/vite/src/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
emptyDir,
getPkgName,
joinUrlSegments,
mergeWithDefaults,
normalizePath,
partialEncodeURIPath,
} from './utils'
Expand Down Expand Up @@ -347,6 +348,44 @@ export interface ResolvedBuildOptions
modulePreload: false | ResolvedModulePreloadOptions
}

export const buildEnvironmentOptionsDefaults = Object.freeze({
target: 'modules',
/** @deprecated */
polyfillModulePreload: true,
modulePreload: true,
outDir: 'dist',
assetsDir: 'assets',
assetsInlineLimit: DEFAULT_ASSETS_INLINE_LIMIT,
// cssCodeSplit
// cssTarget
// cssMinify
sourcemap: false,
// minify
terserOptions: {},
rollupOptions: {},
commonjsOptions: {
include: [/node_modules/],
extensions: ['.js', '.cjs'],
},
dynamicImportVarsOptions: {
warnOnError: true,
exclude: [/node_modules/],
},
write: true,
emptyOutDir: null,
copyPublicDir: true,
manifest: false,
lib: false,
// ssr
ssrManifest: false,
ssrEmitAssets: false,
// emitAssets
reportCompressedSize: true,
chunkSizeWarningLimit: 500,
watch: null,
// createEnvironment
})

export function resolveBuildEnvironmentOptions(
raw: BuildEnvironmentOptions,
logger: Logger,
Expand All @@ -369,84 +408,49 @@ export function resolveBuildEnvironmentOptions(
raw.modulePreload = { polyfill: false }
}

const modulePreload = raw.modulePreload
const defaultModulePreload = {
polyfill: true,
const merged = mergeWithDefaults(
{
...buildEnvironmentOptionsDefaults,
cssCodeSplit: !raw.lib,
minify: consumer === 'server' ? false : 'esbuild',
ssr: consumer === 'server',
emitAssets: consumer === 'client',
createEnvironment: (name, config) => new BuildEnvironment(name, config),
} satisfies BuildEnvironmentOptions,
raw,
)

// handle special build targets
if (merged.target === 'modules') {
merged.target = ESBUILD_MODULES_TARGET
}

const defaultBuildEnvironmentOptions: BuildEnvironmentOptions = {
outDir: 'dist',
assetsDir: 'assets',
assetsInlineLimit: DEFAULT_ASSETS_INLINE_LIMIT,
cssCodeSplit: !raw.lib,
sourcemap: false,
rollupOptions: {},
minify: consumer === 'server' ? false : 'esbuild',
terserOptions: {},
write: true,
emptyOutDir: null,
copyPublicDir: true,
manifest: false,
lib: false,
ssr: consumer === 'server',
ssrManifest: false,
ssrEmitAssets: false,
emitAssets: consumer === 'client',
reportCompressedSize: true,
chunkSizeWarningLimit: 500,
watch: null,
createEnvironment: (name, config) => new BuildEnvironment(name, config),
// normalize false string into actual false
if ((merged.minify as string) === 'false') {
merged.minify = false
} else if (merged.minify === true) {
merged.minify = 'esbuild'
}

const userBuildEnvironmentOptions = raw
? mergeConfig(defaultBuildEnvironmentOptions, raw)
: defaultBuildEnvironmentOptions
const defaultModulePreload = {
polyfill: true,
}

// @ts-expect-error Fallback options instead of merging
const resolved: ResolvedBuildEnvironmentOptions = {
target: 'modules',
cssTarget: false,
...userBuildEnvironmentOptions,
commonjsOptions: {
include: [/node_modules/],
extensions: ['.js', '.cjs'],
...userBuildEnvironmentOptions.commonjsOptions,
},
dynamicImportVarsOptions: {
warnOnError: true,
exclude: [/node_modules/],
...userBuildEnvironmentOptions.dynamicImportVarsOptions,
},
...merged,
cssTarget: merged.cssTarget ?? merged.target,
cssMinify:
merged.cssMinify ?? (consumer === 'server' ? 'esbuild' : !!merged.minify),
// Resolve to false | object
modulePreload:
modulePreload === false
merged.modulePreload === false
? false
: typeof modulePreload === 'object'
? {
: merged.modulePreload === true
? defaultModulePreload
: {
...defaultModulePreload,
...modulePreload,
}
: defaultModulePreload,
}

// handle special build targets
if (resolved.target === 'modules') {
resolved.target = ESBUILD_MODULES_TARGET
}

if (!resolved.cssTarget) {
resolved.cssTarget = resolved.target
}

// normalize false string into actual false
if ((resolved.minify as string) === 'false') {
resolved.minify = false
} else if (resolved.minify === true) {
resolved.minify = 'esbuild'
}

if (resolved.cssMinify == null) {
resolved.cssMinify = consumer === 'server' ? 'esbuild' : !!resolved.minify
...merged.modulePreload,
},
}

if (isSsrTargetWebworkerEnvironment) {
Expand Down Expand Up @@ -1503,15 +1507,20 @@ async function defaultBuildApp(builder: ViteBuilder): Promise<void> {
}
}

export const builderOptionsDefaults = Object.freeze({
sharedConfigBuild: false,
sharedPlugins: false,
// buildApp
})

export function resolveBuilderOptions(
options: BuilderOptions | undefined,
): ResolvedBuilderOptions | undefined {
if (!options) return
return {
sharedConfigBuild: options.sharedConfigBuild ?? false,
sharedPlugins: options.sharedPlugins ?? false,
buildApp: options.buildApp ?? defaultBuildApp,
}
return mergeWithDefaults(
{ ...builderOptionsDefaults, buildApp: defaultBuildApp },
options,
)
}

export type ResolvedBuilderOptions = Required<BuilderOptions>
Expand Down
Loading

0 comments on commit 0e1f437

Please sign in to comment.