From 3b94883414088feccc7d38adafe28cfb37eeadf9 Mon Sep 17 00:00:00 2001 From: Michael Brevard Date: Tue, 9 Jan 2024 11:56:40 +0200 Subject: [PATCH] perf(nuxt): iterate rather than using `Object.fromEntries` (#24953) --- packages/nuxt/src/core/nitro.ts | 21 +++++++++-------- .../nuxt/src/core/plugins/layer-aliasing.ts | 23 ++++++++++--------- packages/nuxt/src/core/templates.ts | 9 ++++++-- packages/nuxt/src/head/runtime/components.ts | 12 ++++++++-- packages/vite/src/plugins/composable-keys.ts | 5 +++- 5 files changed, 44 insertions(+), 26 deletions(-) diff --git a/packages/nuxt/src/core/nitro.ts b/packages/nuxt/src/core/nitro.ts index 8303c4fee7b1..a294eb335d6e 100644 --- a/packages/nuxt/src/core/nitro.ts +++ b/packages/nuxt/src/core/nitro.ts @@ -260,16 +260,17 @@ export async function initNitro (nuxt: Nuxt & { _nitro?: Nitro }) { const _routeRules = nitro.options.routeRules for (const key in _routeRules) { if (key === '/__nuxt_error') { continue } - const filteredRules = Object.entries(_routeRules[key]) - .filter(([key, value]) => ['prerender', 'redirect'].includes(key) && value) - .map(([key, value]: any) => { - if (key === 'redirect') { - return [key, typeof value === 'string' ? value : value.to] - } - return [key, value] - }) - if (filteredRules.length > 0) { - routeRules[key] = Object.fromEntries(filteredRules) + let hasRules = false + const filteredRules = {} as Record + for (const routeKey in _routeRules[key]) { + const value = (_routeRules as any)[key][routeKey] + if (['prerender', 'redirect'].includes(routeKey) && value) { + filteredRules[routeKey] = routeKey === 'redirect' ? typeof value === 'string' ? value : value.to : value + hasRules = true + } + } + if (hasRules) { + routeRules[key] = filteredRules } } diff --git a/packages/nuxt/src/core/plugins/layer-aliasing.ts b/packages/nuxt/src/core/plugins/layer-aliasing.ts index 52dc8bf2bed1..f73f67297f09 100644 --- a/packages/nuxt/src/core/plugins/layer-aliasing.ts +++ b/packages/nuxt/src/core/plugins/layer-aliasing.ts @@ -17,22 +17,23 @@ const ALIAS_RE = /(?<=['"])[~@]{1,2}(?=\/)/g const ALIAS_RE_SINGLE = /(?<=['"])[~@]{1,2}(?=\/)/ export const LayerAliasingPlugin = createUnplugin((options: LayerAliasingOptions) => { - const aliases = Object.fromEntries(options.layers.map((l) => { - const srcDir = l.config.srcDir || l.cwd - const rootDir = l.config.rootDir || l.cwd - const publicDir = join(srcDir, l.config?.dir?.public || 'public') + const aliases: Record, prefix: string, publicDir: false | string }> = {} + for (const layer of options.layers) { + const srcDir = layer.config.srcDir || layer.cwd + const rootDir = layer.config.rootDir || layer.cwd + const publicDir = join(srcDir, layer.config?.dir?.public || 'public') - return [srcDir, { + aliases[srcDir] = { aliases: { - '~': l.config?.alias?.['~'] || srcDir, - '@': l.config?.alias?.['@'] || srcDir, - '~~': l.config?.alias?.['~~'] || rootDir, - '@@': l.config?.alias?.['@@'] || rootDir + '~': layer.config?.alias?.['~'] || srcDir, + '@': layer.config?.alias?.['@'] || srcDir, + '~~': layer.config?.alias?.['~~'] || rootDir, + '@@': layer.config?.alias?.['@@'] || rootDir }, prefix: relative(options.root, publicDir), publicDir: !options.dev && existsSync(publicDir) && publicDir - }] - })) + } + } const layers = Object.keys(aliases).sort((a, b) => b.length - a.length) return { diff --git a/packages/nuxt/src/core/templates.ts b/packages/nuxt/src/core/templates.ts index 3ce3c868b3f6..a378707d2009 100644 --- a/packages/nuxt/src/core/templates.ts +++ b/packages/nuxt/src/core/templates.ts @@ -155,7 +155,12 @@ export const schemaTemplate: NuxtTemplate = { const relativeRoot = relative(resolve(nuxt.options.buildDir, 'types'), nuxt.options.rootDir) const getImportName = (name: string) => (name[0] === '.' ? './' + join(relativeRoot, name) : name).replace(/\.\w+$/, '') const modules = moduleInfo.map(meta => [genString(meta.configKey), getImportName(meta.importName)]) - + const privateRuntimeConfig = Object.create(null) + for (const key in nuxt.options.runtimeConfig) { + if (key !== 'public') { + privateRuntimeConfig[key] = nuxt.options.runtimeConfig[key] + } + } return [ "import { NuxtModule, RuntimeConfig } from 'nuxt/schema'", "declare module 'nuxt/schema' {", @@ -165,7 +170,7 @@ export const schemaTemplate: NuxtTemplate = { ), modules.length > 0 ? ` modules?: (undefined | null | false | NuxtModule | string | [NuxtModule | string, Record] | ${modules.map(([configKey, importName]) => `[${genString(importName)}, Exclude]`).join(' | ')})[],` : '', ' }', - generateTypes(await resolveSchema(Object.fromEntries(Object.entries(nuxt.options.runtimeConfig).filter(([key]) => key !== 'public')) as Record), + generateTypes(await resolveSchema(privateRuntimeConfig as Record), { interfaceName: 'RuntimeConfig', addExport: false, diff --git a/packages/nuxt/src/head/runtime/components.ts b/packages/nuxt/src/head/runtime/components.ts index 37d1df42245c..3ed7a1ee069c 100644 --- a/packages/nuxt/src/head/runtime/components.ts +++ b/packages/nuxt/src/head/runtime/components.ts @@ -12,8 +12,16 @@ import type { Target } from './types' -const removeUndefinedProps = (props: Props) => - Object.fromEntries(Object.entries(props).filter(([, value]) => value !== undefined)) +const removeUndefinedProps = (props: Props) => { + const filteredProps = Object.create(null) + for (const key in props) { + const value = props[key] + if (value !== undefined) { + filteredProps[key] = value; + } + } + return filteredProps +} const setupForUseMeta = (metaFactory: (props: Props, ctx: SetupContext) => Record, renderChild?: boolean) => (props: Props, ctx: SetupContext) => { useHead(() => metaFactory({ ...removeUndefinedProps(props), ...ctx.attrs }, ctx)) diff --git a/packages/vite/src/plugins/composable-keys.ts b/packages/vite/src/plugins/composable-keys.ts index 1a46b3d2d105..a160545b598c 100644 --- a/packages/vite/src/plugins/composable-keys.ts +++ b/packages/vite/src/plugins/composable-keys.ts @@ -22,7 +22,10 @@ const NUXT_LIB_RE = /node_modules\/(nuxt|nuxt3|nuxt-nightly)\// const SUPPORTED_EXT_RE = /\.(m?[jt]sx?|vue)/ export const composableKeysPlugin = createUnplugin((options: ComposableKeysOptions) => { - const composableMeta = Object.fromEntries(options.composables.map(({ name, ...meta }) => [name, meta])) + const composableMeta: Record = {} + for (const { name, ...meta } of options.composables) { + composableMeta[name] = meta + } const maxLength = Math.max(...options.composables.map(({ argumentLength }) => argumentLength)) const keyedFunctions = new Set(options.composables.map(({ name }) => name))