From 07146ddf48284361c9ea2ae6fa07efdc53eda776 Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Wed, 15 Jan 2025 01:36:18 +0800 Subject: [PATCH] refactor(kit,nuxt,webpack): reduce reassignments (#30589) --- packages/kit/src/build.ts | 6 +++--- packages/kit/src/components.ts | 4 ++-- packages/kit/src/loader/config.ts | 2 +- packages/kit/src/loader/nuxt.ts | 2 +- packages/kit/src/module/define.ts | 2 +- packages/kit/src/module/install.ts | 2 +- packages/kit/src/nitro.ts | 12 ++++++------ packages/kit/src/pages.ts | 4 +--- packages/kit/src/plugin.ts | 4 ++-- packages/kit/src/template.ts | 9 +++++---- packages/kit/src/utils.ts | 15 +++++++++++++++ packages/nuxt/src/app/components/client-only.ts | 2 +- packages/nuxt/src/app/composables/once.ts | 2 +- packages/nuxt/src/components/module.ts | 4 ++-- packages/nuxt/src/core/nitro.ts | 16 +++++++++++----- packages/nuxt/src/core/runtime/nitro/no-ssr.ts | 2 +- packages/nuxt/src/core/runtime/nitro/renderer.ts | 4 ++-- packages/nuxt/src/pages/module.ts | 4 ++-- packages/webpack/src/configs/client.ts | 4 ++-- packages/webpack/src/configs/server.ts | 2 +- packages/webpack/src/presets/base.ts | 2 +- 21 files changed, 62 insertions(+), 42 deletions(-) diff --git a/packages/kit/src/build.ts b/packages/kit/src/build.ts index ba4a1d17ba..0f3bb8f48c 100644 --- a/packages/kit/src/build.ts +++ b/packages/kit/src/build.ts @@ -114,7 +114,7 @@ export function addWebpackPlugin (pluginOrGetter: WebpackPluginInstance | Webpac const method: 'push' | 'unshift' = options?.prepend ? 'unshift' : 'push' const plugin = typeof pluginOrGetter === 'function' ? pluginOrGetter() : pluginOrGetter - config.plugins = config.plugins || [] + config.plugins ||= [] config.plugins[method](...toArray(plugin)) }, options) } @@ -126,7 +126,7 @@ export function addRspackPlugin (pluginOrGetter: RspackPluginInstance | RspackPl const method: 'push' | 'unshift' = options?.prepend ? 'unshift' : 'push' const plugin = typeof pluginOrGetter === 'function' ? pluginOrGetter() : pluginOrGetter - config.plugins = config.plugins || [] + config.plugins ||= [] config.plugins[method](...toArray(plugin)) }, options) } @@ -139,7 +139,7 @@ export function addVitePlugin (pluginOrGetter: VitePlugin | VitePlugin[] | (() = const method: 'push' | 'unshift' = options?.prepend ? 'unshift' : 'push' const plugin = typeof pluginOrGetter === 'function' ? pluginOrGetter() : pluginOrGetter - config.plugins = config.plugins || [] + config.plugins ||= [] config.plugins[method](...toArray(plugin)) }, options) } diff --git a/packages/kit/src/components.ts b/packages/kit/src/components.ts index 82394e3811..b10fd98f16 100644 --- a/packages/kit/src/components.ts +++ b/packages/kit/src/components.ts @@ -11,7 +11,7 @@ import { MODE_RE } from './utils' export async function addComponentsDir (dir: ComponentsDir, opts: { prepend?: boolean } = {}) { const nuxt = useNuxt() await assertNuxtCompatibility({ nuxt: '>=2.13' }, nuxt) - nuxt.options.components = nuxt.options.components || [] + nuxt.options.components ||= [] dir.priority ||= 0 nuxt.hook('components:dirs', (dirs) => { dirs[opts.prepend ? 'unshift' : 'push'](dir) }) } @@ -26,7 +26,7 @@ export type AddComponentOptions = { name: string, filePath: string } & Partial=2.13' }, nuxt) - nuxt.options.components = nuxt.options.components || [] + nuxt.options.components ||= [] if (!opts.mode) { const [, mode = 'all'] = opts.filePath.match(MODE_RE) || [] diff --git a/packages/kit/src/loader/config.ts b/packages/kit/src/loader/config.ts index 80139fb015..74652c9b43 100644 --- a/packages/kit/src/loader/config.ts +++ b/packages/kit/src/loader/config.ts @@ -58,7 +58,7 @@ export async function loadNuxtConfig (opts: LoadNuxtConfigOptions): Promise() for (const layer of layers) { // Resolve `rootDir` & `srcDir` of layers - layer.config = layer.config || {} + layer.config ||= {} layer.config.rootDir = layer.config.rootDir ?? layer.cwd! // Only process/resolve layers once diff --git a/packages/kit/src/loader/nuxt.ts b/packages/kit/src/loader/nuxt.ts index 892286f5b6..71e60a908e 100644 --- a/packages/kit/src/loader/nuxt.ts +++ b/packages/kit/src/loader/nuxt.ts @@ -16,7 +16,7 @@ export interface LoadNuxtOptions extends LoadNuxtConfigOptions { export async function loadNuxt (opts: LoadNuxtOptions): Promise { // Backward compatibility opts.cwd = resolve(opts.cwd || (opts as any).rootDir /* backwards compat */ || '.') - opts.overrides = opts.overrides || (opts as any).config as NuxtConfig /* backwards compat */ || {} + opts.overrides ||= (opts as any).config as NuxtConfig /* backwards compat */ || {} // Apply dev as config override opts.overrides.dev = !!opts.dev diff --git a/packages/kit/src/module/define.ts b/packages/kit/src/module/define.ts index b0f30d80fb..4624692527 100644 --- a/packages/kit/src/module/define.ts +++ b/packages/kit/src/module/define.ts @@ -87,7 +87,7 @@ function _defineNuxtModule< // Avoid duplicate installs const uniqueKey = module.meta.name || module.meta.configKey if (uniqueKey) { - nuxt.options._requiredModules = nuxt.options._requiredModules || {} + nuxt.options._requiredModules ||= {} if (nuxt.options._requiredModules[uniqueKey]) { return false } diff --git a/packages/kit/src/module/install.ts b/packages/kit/src/module/install.ts index 5164f512f4..8b1348dbd2 100644 --- a/packages/kit/src/module/install.ts +++ b/packages/kit/src/module/install.ts @@ -44,7 +44,7 @@ export async function installModule< } } - nuxt.options._installedModules = nuxt.options._installedModules || [] + nuxt.options._installedModules ||= [] const entryPath = typeof moduleToInstall === 'string' ? resolveAlias(moduleToInstall) : undefined if (typeof moduleToInstall === 'string' && entryPath !== moduleToInstall) { diff --git a/packages/kit/src/nitro.ts b/packages/kit/src/nitro.ts index 4c046f6a9d..361c3c7872 100644 --- a/packages/kit/src/nitro.ts +++ b/packages/kit/src/nitro.ts @@ -40,7 +40,7 @@ export function addDevServerHandler (handler: NitroDevEventHandler) { */ export function addServerPlugin (plugin: string) { const nuxt = useNuxt() - nuxt.options.nitro.plugins = nuxt.options.nitro.plugins || [] + nuxt.options.nitro.plugins ||= [] nuxt.options.nitro.plugins.push(normalize(plugin)) } @@ -89,8 +89,8 @@ export function useNitro (): Nitro { export function addServerImports (imports: Import[]) { const nuxt = useNuxt() nuxt.hook('nitro:config', (config) => { - config.imports = config.imports || {} - config.imports.imports = config.imports.imports || [] + config.imports ||= {} + config.imports.imports ||= [] config.imports.imports.push(...imports) }) } @@ -102,8 +102,8 @@ export function addServerImportsDir (dirs: string | string[], opts: { prepend?: const nuxt = useNuxt() const _dirs = toArray(dirs) nuxt.hook('nitro:config', (config) => { - config.imports = config.imports || {} - config.imports.dirs = config.imports.dirs || [] + config.imports ||= {} + config.imports.dirs ||= [] config.imports.dirs[opts.prepend ? 'unshift' : 'push'](..._dirs) }) } @@ -115,7 +115,7 @@ export function addServerImportsDir (dirs: string | string[], opts: { prepend?: export function addServerScanDir (dirs: string | string[], opts: { prepend?: boolean } = {}) { const nuxt = useNuxt() nuxt.hook('nitro:config', (config) => { - config.scanDirs = config.scanDirs || [] + config.scanDirs ||= [] for (const dir of toArray(dirs)) { config.scanDirs[opts.prepend ? 'unshift' : 'push'](dir) diff --git a/packages/kit/src/pages.ts b/packages/kit/src/pages.ts index 35c73fae83..dbb153487e 100644 --- a/packages/kit/src/pages.ts +++ b/packages/kit/src/pages.ts @@ -20,9 +20,7 @@ export interface ExtendRouteRulesOptions { export function extendRouteRules (route: string, rule: NitroRouteConfig, options: ExtendRouteRulesOptions = {}) { const nuxt = useNuxt() for (const opts of [nuxt.options, nuxt.options.nitro]) { - if (!opts.routeRules) { - opts.routeRules = {} - } + opts.routeRules ||= {} opts.routeRules[route] = options.override ? defu(rule, opts.routeRules[route]) : defu(opts.routeRules[route], rule) diff --git a/packages/kit/src/plugin.ts b/packages/kit/src/plugin.ts index b89d9642be..26ae9b70dc 100644 --- a/packages/kit/src/plugin.ts +++ b/packages/kit/src/plugin.ts @@ -5,10 +5,10 @@ import { normalize } from 'pathe' import type { NuxtPlugin, NuxtPluginTemplate } from '@nuxt/schema' import { resolvePathSync } from 'mlly' import { isWindows } from 'std-env' +import { MODE_RE, filterInPlace } from './utils' import { tryUseNuxt, useNuxt } from './context' import { addTemplate } from './template' import { resolveAlias } from './resolve' -import { MODE_RE } from './utils' /** * Normalize a nuxt plugin object @@ -82,7 +82,7 @@ export function addPlugin (_plugin: NuxtPlugin | string, opts: AddPluginOptions const plugin = normalizePlugin(_plugin) // Remove any existing plugin with the same src - nuxt.options.plugins = nuxt.options.plugins.filter(p => normalizePlugin(p).src !== plugin.src) + filterInPlace(nuxt.options.plugins, p => normalizePlugin(p).src !== plugin.src) // Prepend to array by default to be before user provided plugins since is usually used by modules nuxt.options.plugins[opts.append ? 'push' : 'unshift'](plugin) diff --git a/packages/kit/src/template.ts b/packages/kit/src/template.ts index 8fa065fad7..9bb78f0f28 100644 --- a/packages/kit/src/template.ts +++ b/packages/kit/src/template.ts @@ -8,6 +8,7 @@ import type { TSConfig } from 'pkg-types' import { gte } from 'semver' import { readPackageJSON } from 'pkg-types' +import { filterInPlace } from './utils' import { tryResolveModule } from './internal/esm' import { getDirectory } from './module/install' import { tryUseNuxt, useNuxt } from './context' @@ -23,7 +24,7 @@ export function addTemplate (_template: NuxtTemplate | string) { const template = normalizeTemplate(_template) // Remove any existing template with the same destination path - nuxt.options.build.templates = nuxt.options.build.templates.filter(p => normalizeTemplate(p).dst !== template.dst) + filterInPlace(nuxt.options.build.templates, p => normalizeTemplate(p).dst !== template.dst) // Add to templates array nuxt.options.build.templates.push(template) @@ -229,9 +230,9 @@ export async function _generateTypes (nuxt: Nuxt) { ? resolve(nuxt.options.buildDir, tsConfig.compilerOptions!.baseUrl) : nuxt.options.buildDir - tsConfig.compilerOptions = tsConfig.compilerOptions || {} - tsConfig.compilerOptions.paths = tsConfig.compilerOptions.paths || {} - tsConfig.include = tsConfig.include || [] + tsConfig.compilerOptions ||= {} + tsConfig.compilerOptions.paths ||= {} + tsConfig.include ||= [] for (const alias in aliases) { if (excludedAlias.some(re => re.test(alias))) { diff --git a/packages/kit/src/utils.ts b/packages/kit/src/utils.ts index 89fa591c50..0816bcf5cd 100644 --- a/packages/kit/src/utils.ts +++ b/packages/kit/src/utils.ts @@ -3,4 +3,19 @@ export function toArray (value: T | T[]): T[] { return Array.isArray(value) ? value : [value] } +/** + * Filter out items from an array in place. This function mutates the array. + * `predicate` get through the array from the end to the start for performance. + * + * This function should be faster than `Array.prototype.filter` on large arrays. + */ +export function filterInPlace (array: T[], predicate: (item: T, index: number, arr: T[]) => unknown) { + for (let i = array.length; i--; i >= 0) { + if (!predicate(array[i]!, i, array)) { + array.splice(i, 1) + } + } + return array +} + export const MODE_RE = /\.(server|client)(\.\w+)*$/ diff --git a/packages/nuxt/src/app/components/client-only.ts b/packages/nuxt/src/app/components/client-only.ts index c65eec1b55..46149f6a79 100644 --- a/packages/nuxt/src/app/components/client-only.ts +++ b/packages/nuxt/src/app/components/client-only.ts @@ -95,7 +95,7 @@ export function createClientOnly (component: T) { if (isPromise(setupState)) { return Promise.resolve(setupState).then((setupState) => { if (typeof setupState !== 'function') { - setupState = setupState || {} + setupState ||= {} setupState.mounted$ = mounted$ return setupState } diff --git a/packages/nuxt/src/app/composables/once.ts b/packages/nuxt/src/app/composables/once.ts index ae8746fff0..7bd3a98c23 100644 --- a/packages/nuxt/src/app/composables/once.ts +++ b/packages/nuxt/src/app/composables/once.ts @@ -37,7 +37,7 @@ export async function callOnce (...args: any): Promise { return } - nuxtApp._once = nuxtApp._once || {} + nuxtApp._once ||= {} nuxtApp._once[_key] = nuxtApp._once[_key] || fn() || true await nuxtApp._once[_key] nuxtApp.payload.once.add(_key) diff --git a/packages/nuxt/src/components/module.ts b/packages/nuxt/src/components/module.ts index f61061e5d9..97d318c12c 100644 --- a/packages/nuxt/src/components/module.ts +++ b/packages/nuxt/src/components/module.ts @@ -250,7 +250,7 @@ export default defineNuxtModule({ // TODO: refactor this nuxt.hook('vite:extendConfig', (config, { isClient }) => { - config.plugins = config.plugins || [] + config.plugins ||= [] if (isClient && selectiveClient) { writeFileSync(join(nuxt.options.buildDir, 'components-chunk.mjs'), 'export const paths = {}') @@ -275,7 +275,7 @@ export default defineNuxtModule({ nuxt.hook(key, (configs) => { configs.forEach((config) => { const mode = config.name === 'client' ? 'client' : 'server' - config.plugins = config.plugins || [] + config.plugins ||= [] if (mode !== 'server') { writeFileSync(join(nuxt.options.buildDir, 'components-chunk.mjs'), 'export const paths = {}') diff --git a/packages/nuxt/src/core/nitro.ts b/packages/nuxt/src/core/nitro.ts index 698cb04b3a..085a2d8f80 100644 --- a/packages/nuxt/src/core/nitro.ts +++ b/packages/nuxt/src/core/nitro.ts @@ -239,7 +239,11 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { // Resolve user-provided paths nitroConfig.srcDir = resolve(nuxt.options.rootDir, nuxt.options.srcDir, nitroConfig.srcDir!) - nitroConfig.ignore = [...(nitroConfig.ignore || []), ...resolveIgnorePatterns(nitroConfig.srcDir), `!${join(nuxt.options.buildDir, 'dist/client', nuxt.options.app.buildAssetsDir, '**/*')}`] + nitroConfig.ignore ||= [] + nitroConfig.ignore.push( + ...resolveIgnorePatterns(nitroConfig.srcDir), + `!${join(nuxt.options.buildDir, 'dist/client', nuxt.options.app.buildAssetsDir, '**/*')}`, + ) // Resolve aliases in user-provided input - so `~/server/test` will work nitroConfig.plugins = nitroConfig.plugins?.map(plugin => plugin ? resolveAlias(plugin, nuxt.options.alias) : plugin) @@ -411,14 +415,16 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { const basePath = nitroConfig.typescript!.tsConfig!.compilerOptions?.baseUrl ? resolve(nuxt.options.buildDir, nitroConfig.typescript!.tsConfig!.compilerOptions?.baseUrl) : nuxt.options.buildDir const aliases = nitroConfig.alias! const tsConfig = nitroConfig.typescript!.tsConfig! - tsConfig.compilerOptions = tsConfig.compilerOptions || {} - tsConfig.compilerOptions.paths = tsConfig.compilerOptions.paths || {} + tsConfig.compilerOptions ||= {} + tsConfig.compilerOptions.paths ||= {} for (const _alias in aliases) { const alias = _alias as keyof typeof aliases if (excludedAlias.some(pattern => typeof pattern === 'string' ? alias === pattern : pattern.test(alias))) { continue } - if (alias in tsConfig.compilerOptions.paths) { continue } + if (alias in tsConfig.compilerOptions.paths) { + continue + } const absolutePath = resolve(basePath, aliases[alias]!) const stats = await fsp.stat(absolutePath).catch(() => null /* file does not exist */) @@ -532,7 +538,7 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { await writeTypes(nitro) } // Exclude nitro output dir from typescript - opts.tsConfig.exclude = opts.tsConfig.exclude || [] + opts.tsConfig.exclude ||= [] opts.tsConfig.exclude.push(relative(nuxt.options.buildDir, resolve(nuxt.options.rootDir, nitro.options.output.dir))) opts.references.push({ path: resolve(nuxt.options.buildDir, 'types/nitro.d.ts') }) }) diff --git a/packages/nuxt/src/core/runtime/nitro/no-ssr.ts b/packages/nuxt/src/core/runtime/nitro/no-ssr.ts index 556c3f98e5..d6ede3076d 100644 --- a/packages/nuxt/src/core/runtime/nitro/no-ssr.ts +++ b/packages/nuxt/src/core/runtime/nitro/no-ssr.ts @@ -2,7 +2,7 @@ import { defineEventHandler, getRequestHeader } from 'h3' export default defineEventHandler((event) => { if (getRequestHeader(event, 'x-nuxt-no-ssr')) { - event.context.nuxt = event.context.nuxt || {} + event.context.nuxt ||= {} event.context.nuxt.noSSR = true } }) diff --git a/packages/nuxt/src/core/runtime/nitro/renderer.ts b/packages/nuxt/src/core/runtime/nitro/renderer.ts index bed864aeb5..7be579a7b3 100644 --- a/packages/nuxt/src/core/runtime/nitro/renderer.ts +++ b/packages/nuxt/src/core/runtime/nitro/renderer.ts @@ -488,8 +488,8 @@ export default defineRenderHandler(async (event): Promise 'export { START_LOCATION, useRoute } from \'vue-router\'', }) - nuxt.options.vite.resolve = nuxt.options.vite.resolve || {} - nuxt.options.vite.resolve.dedupe = nuxt.options.vite.resolve.dedupe || [] + nuxt.options.vite.resolve ||= {} + nuxt.options.vite.resolve.dedupe ||= [] nuxt.options.vite.resolve.dedupe.push('vue-router') // Add router options template diff --git a/packages/webpack/src/configs/client.ts b/packages/webpack/src/configs/client.ts index f147745939..da08af89a2 100644 --- a/packages/webpack/src/configs/client.ts +++ b/packages/webpack/src/configs/client.ts @@ -56,7 +56,7 @@ function clientNodeCompat (ctx: WebpackConfigContext) { } ctx.config.plugins!.push(new webpack.DefinePlugin({ global: 'globalThis' })) - ctx.config.resolve = ctx.config.resolve || {} + ctx.config.resolve ||= {} ctx.config.resolve.fallback = { ...env(nodeless).alias, ...ctx.config.resolve.fallback, @@ -92,7 +92,7 @@ function clientHMR (ctx: WebpackConfigContext) { `webpack-hot-middleware/client?${hotMiddlewareClientOptionsStr}`, ) - ctx.config.plugins = ctx.config.plugins || [] + ctx.config.plugins ||= [] ctx.config.plugins.push(new webpack.HotModuleReplacementPlugin()) } diff --git a/packages/webpack/src/configs/server.ts b/packages/webpack/src/configs/server.ts index 574b930e7f..64347f78a7 100644 --- a/packages/webpack/src/configs/server.ts +++ b/packages/webpack/src/configs/server.ts @@ -85,7 +85,7 @@ function serverStandalone (ctx: WebpackConfigContext) { } function serverPlugins (ctx: WebpackConfigContext) { - ctx.config.plugins = ctx.config.plugins || [] + ctx.config.plugins ||= [] // Server polyfills if (ctx.userConfig.serverURLPolyfill) { diff --git a/packages/webpack/src/presets/base.ts b/packages/webpack/src/presets/base.ts index 4e80ea8c54..bafceb8291 100644 --- a/packages/webpack/src/presets/base.ts +++ b/packages/webpack/src/presets/base.ts @@ -50,7 +50,7 @@ function baseConfig (ctx: WebpackConfigContext) { } function basePlugins (ctx: WebpackConfigContext) { - ctx.config.plugins = ctx.config.plugins || [] + ctx.config.plugins ||= [] // Add timefix-plugin before other plugins if (ctx.options.dev) {