From c37ebab1ef5eb163e88f551416d664efb9077c20 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Mon, 22 May 2023 21:25:42 +0100 Subject: [PATCH] perf(nuxt): use `.test` and hoist regexps where possible (#21011) --- packages/nuxi/src/commands/dev.ts | 4 +++- .../nuxt/src/components/client-fallback-auto-id.ts | 4 ++-- packages/nuxt/src/components/loader.ts | 4 ++-- packages/nuxt/src/components/transform.ts | 4 +++- packages/nuxt/src/core/nuxt.ts | 4 +++- packages/nuxt/src/core/plugins/dev-only.ts | 2 +- packages/nuxt/src/core/plugins/layer-aliasing.ts | 3 ++- packages/nuxt/src/imports/transform.ts | 11 +++++++---- packages/nuxt/src/pages/module.ts | 6 ++++-- packages/nuxt/src/pages/page-meta.ts | 4 +++- packages/vite/src/plugins/composable-keys.ts | 4 +++- packages/vite/src/plugins/ssr-styles.ts | 4 +++- packages/webpack/src/plugins/vue/server.ts | 4 +++- 13 files changed, 39 insertions(+), 19 deletions(-) diff --git a/packages/nuxi/src/commands/dev.ts b/packages/nuxi/src/commands/dev.ts index cdf7c77aef..7886c577ea 100644 --- a/packages/nuxi/src/commands/dev.ts +++ b/packages/nuxi/src/commands/dev.ts @@ -172,7 +172,7 @@ export default defineNuxtCommand({ watcher.on('all', (_event, _file) => { const file = relative(rootDir, _file) if (file === (args.dotenv || '.env')) { return hardRestart('.env updated') } - if (file.match(/^(nuxt\.config\.(js|ts|mjs|cjs)|\.nuxtignore|\.nuxtrc)$/)) { + if (RESTART_RE.test(file)) { dLoad(true, `${file} updated`) } }) @@ -182,3 +182,5 @@ export default defineNuxtCommand({ return 'wait' as const } }) + +const RESTART_RE = /^(nuxt\.config\.(js|ts|mjs|cjs)|\.nuxtignore|\.nuxtrc)$/ diff --git a/packages/nuxt/src/components/client-fallback-auto-id.ts b/packages/nuxt/src/components/client-fallback-auto-id.ts index 88af5d8d2e..3f01c80c25 100644 --- a/packages/nuxt/src/components/client-fallback-auto-id.ts +++ b/packages/nuxt/src/components/client-fallback-auto-id.ts @@ -19,10 +19,10 @@ export const clientFallbackAutoIdPlugin = createUnplugin((options: LoaderOptions name: 'nuxt:client-fallback-auto-id', enforce: 'pre', transformInclude (id) { - if (exclude.some(pattern => id.match(pattern))) { + if (exclude.some(pattern => pattern.test(id))) { return false } - if (include.some(pattern => id.match(pattern))) { + if (include.some(pattern => pattern.test(id))) { return true } return isVue(id) diff --git a/packages/nuxt/src/components/loader.ts b/packages/nuxt/src/components/loader.ts index b496494016..7063174faf 100644 --- a/packages/nuxt/src/components/loader.ts +++ b/packages/nuxt/src/components/loader.ts @@ -25,10 +25,10 @@ export const loaderPlugin = createUnplugin((options: LoaderOptions) => { name: 'nuxt:components-loader', enforce: 'post', transformInclude (id) { - if (exclude.some(pattern => id.match(pattern))) { + if (exclude.some(pattern => pattern.test(id))) { return false } - if (include.some(pattern => id.match(pattern))) { + if (include.some(pattern => pattern.test(id))) { return true } return isVue(id, { type: ['template', 'script'] }) diff --git a/packages/nuxt/src/components/transform.ts b/packages/nuxt/src/components/transform.ts index e4bda7dcbf..3872703cd7 100644 --- a/packages/nuxt/src/components/transform.ts +++ b/packages/nuxt/src/components/transform.ts @@ -7,6 +7,8 @@ import { parseURL } from 'ufo' import { parseQuery } from 'vue-router' import type { getComponentsT } from './module' +const COMPONENT_QUERY_RE = /[?&]nuxt_component=/ + export function createTransformPlugin (nuxt: Nuxt, getComponents: getComponentsT, mode: 'client' | 'server' | 'all') { const componentUnimport = createUnimport({ imports: [ @@ -47,7 +49,7 @@ export function createTransformPlugin (nuxt: Nuxt, getComponents: getComponentsT }, async transform (code, id) { // Virtual component wrapper - if (id.match(/[?&]nuxt_component=/)) { + if (COMPONENT_QUERY_RE.test(id)) { const { search } = parseURL(id) const query = parseQuery(search) const mode = query.nuxt_component diff --git a/packages/nuxt/src/core/nuxt.ts b/packages/nuxt/src/core/nuxt.ts index 182a7bb337..eb3647e0f9 100644 --- a/packages/nuxt/src/core/nuxt.ts +++ b/packages/nuxt/src/core/nuxt.ts @@ -363,7 +363,7 @@ async function initNuxt (nuxt: Nuxt) { // Core Nuxt files: app.vue, error.vue and app.config.ts const isFileChange = ['add', 'unlink'].includes(event) - if (isFileChange && path.match(/^(app|error|app\.config)\.(js|ts|mjs|jsx|tsx|vue)$/i)) { + if (isFileChange && RESTART_RE.test(path)) { console.info(`\`${path}\` ${event === 'add' ? 'created' : 'removed'}`) return nuxt.callHook('restart') } @@ -427,3 +427,5 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise { return nuxt } + +const RESTART_RE = /^(app|error|app\.config)\.(js|ts|mjs|jsx|tsx|vue)$/i diff --git a/packages/nuxt/src/core/plugins/dev-only.ts b/packages/nuxt/src/core/plugins/dev-only.ts index b14b4f6a74..0cd7a40f2b 100644 --- a/packages/nuxt/src/core/plugins/dev-only.ts +++ b/packages/nuxt/src/core/plugins/dev-only.ts @@ -25,7 +25,7 @@ export const DevOnlyPlugin = createUnplugin((options: DevOnlyPluginOptions) => { } }, transform (code) { - if (!code.match(DEVONLY_COMP_RE)) { return } + if (!DEVONLY_COMP_RE.test(code)) { return } const s = new MagicString(code) const strippedCode = stripLiteral(code) diff --git a/packages/nuxt/src/core/plugins/layer-aliasing.ts b/packages/nuxt/src/core/plugins/layer-aliasing.ts index c085452a38..52dc8bf2be 100644 --- a/packages/nuxt/src/core/plugins/layer-aliasing.ts +++ b/packages/nuxt/src/core/plugins/layer-aliasing.ts @@ -14,6 +14,7 @@ interface LayerAliasingOptions { } 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) => { @@ -71,7 +72,7 @@ export const LayerAliasingPlugin = createUnplugin((options: LayerAliasingOptions const _id = normalize(id) const layer = layers.find(l => _id.startsWith(l)) - if (!layer || !code.match(ALIAS_RE)) { return } + if (!layer || !ALIAS_RE_SINGLE.test(code)) { return } const s = new MagicString(code) s.replace(ALIAS_RE, r => aliases[layer].aliases[r as '~'] || r) diff --git a/packages/nuxt/src/imports/transform.ts b/packages/nuxt/src/imports/transform.ts index e623d81d49..5a82bad059 100644 --- a/packages/nuxt/src/imports/transform.ts +++ b/packages/nuxt/src/imports/transform.ts @@ -4,17 +4,20 @@ import { normalize } from 'pathe' import type { ImportsOptions } from 'nuxt/schema' import { isJS, isVue } from '../core/utils' +const NODE_MODULES_RE = /[\\/]node_modules[\\/]/ +const IMPORTS_RE = /(['"])#imports\1/ + export const TransformPlugin = createUnplugin(({ ctx, options, sourcemap }: { ctx: Unimport, options: Partial, sourcemap?: boolean }) => { return { name: 'nuxt:imports-transform', enforce: 'post', transformInclude (id) { // Included - if (options.transform?.include?.some(pattern => id.match(pattern))) { + if (options.transform?.include?.some(pattern => pattern.test(id))) { return true } // Excluded - if (options.transform?.exclude?.some(pattern => id.match(pattern))) { + if (options.transform?.exclude?.some(pattern => pattern.test(id))) { return false } @@ -28,9 +31,9 @@ export const TransformPlugin = createUnplugin(({ ctx, options, sourcemap }: { ct }, async transform (code, id) { id = normalize(id) - const isNodeModule = id.match(/[\\/]node_modules[\\/]/) && !options.transform?.include?.some(pattern => id.match(pattern)) + const isNodeModule = NODE_MODULES_RE.test(id) && !options.transform?.include?.some(pattern => pattern.test(id)) // For modules in node_modules, we only transform `#imports` but not doing imports - if (isNodeModule && !code.match(/(['"])#imports\1/)) { + if (isNodeModule && !IMPORTS_RE.test(code)) { return } diff --git a/packages/nuxt/src/pages/module.ts b/packages/nuxt/src/pages/module.ts index c3de3ab0ef..9744f7d7ef 100644 --- a/packages/nuxt/src/pages/module.ts +++ b/packages/nuxt/src/pages/module.ts @@ -15,6 +15,8 @@ import { normalizeRoutes, resolvePagesRoutes } from './utils' import type { PageMetaPluginOptions } from './page-meta' import { PageMetaPlugin } from './page-meta' +const OPTIONAL_PARAM_RE = /^\/?:.*(\?|\(\.\*\)\*)$/ + export default defineNuxtModule({ meta: { name: 'pages' @@ -180,7 +182,7 @@ export default defineNuxtModule({ ].filter(Boolean) const pathPattern = new RegExp(`(^|\\/)(${dirs.map(escapeRE).join('|')})/`) - if (event !== 'change' && path.match(pathPattern)) { + if (event !== 'change' && pathPattern.test(path)) { await updateTemplates({ filter: template => template.filename === 'routes.mjs' }) @@ -208,7 +210,7 @@ export default defineNuxtModule({ const processPages = (pages: NuxtPage[], currentPath = '/') => { for (const page of pages) { // Add root of optional dynamic paths and catchalls - if (page.path.match(/^\/?:.*(\?|\(\.\*\)\*)$/) && !page.children?.length) { prerenderRoutes.add(currentPath) } + if (OPTIONAL_PARAM_RE.test(page.path) && !page.children?.length) { prerenderRoutes.add(currentPath) } // Skip dynamic paths if (page.path.includes(':')) { continue } const route = joinURL(currentPath, page.path) diff --git a/packages/nuxt/src/pages/page-meta.ts b/packages/nuxt/src/pages/page-meta.ts index 7563b436fa..5199f9f8a6 100644 --- a/packages/nuxt/src/pages/page-meta.ts +++ b/packages/nuxt/src/pages/page-meta.ts @@ -14,6 +14,8 @@ export interface PageMetaPluginOptions { sourcemap?: boolean } +const HAS_MACRO_RE = /\bdefinePageMeta\s*\(\s*/ + const CODE_EMPTY = ` const __nuxt_page_meta = null export default __nuxt_page_meta @@ -59,7 +61,7 @@ export const PageMetaPlugin = createUnplugin((options: PageMetaPluginOptions) => } } - const hasMacro = code.match(/\bdefinePageMeta\s*\(\s*/) + const hasMacro = HAS_MACRO_RE.test(code) const imports = findStaticImports(code) diff --git a/packages/vite/src/plugins/composable-keys.ts b/packages/vite/src/plugins/composable-keys.ts index 70eee4edab..336f1b96bd 100644 --- a/packages/vite/src/plugins/composable-keys.ts +++ b/packages/vite/src/plugins/composable-keys.ts @@ -17,6 +17,8 @@ export interface ComposableKeysOptions { } const stringTypes = ['Literal', 'TemplateLiteral'] +const NUXT_LIB_RE = /node_modules\/nuxt3?\// +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])) @@ -30,7 +32,7 @@ export const composableKeysPlugin = createUnplugin((options: ComposableKeysOptio enforce: 'post', transformInclude (id) { const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href)) - return !pathname.match(/node_modules\/nuxt3?\//) && pathname.match(/\.(m?[jt]sx?|vue)/) && parseQuery(search).type !== 'style' && !parseQuery(search).macro + return !NUXT_LIB_RE.test(pathname) && SUPPORTED_EXT_RE.test(pathname) && parseQuery(search).type !== 'style' && !parseQuery(search).macro }, transform (code, id) { if (!KEYED_FUNCTIONS_RE.test(code)) { return } diff --git a/packages/vite/src/plugins/ssr-styles.ts b/packages/vite/src/plugins/ssr-styles.ts index da9b0e89f6..0ef84cefb0 100644 --- a/packages/vite/src/plugins/ssr-styles.ts +++ b/packages/vite/src/plugins/ssr-styles.ts @@ -14,6 +14,8 @@ interface SSRStylePluginOptions { components: Component[] } +const SUPPORTED_FILES_RE = /\.(vue|((c|m)?j|t)sx?)$/ + export function ssrStylesPlugin (options: SSRStylePluginOptions): Plugin { const cssMap: Record = {} const idRefMap: Record = {} @@ -101,7 +103,7 @@ export function ssrStylesPlugin (options: SSRStylePluginOptions): Plugin { const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href)) const query = parseQuery(search) - if (!pathname.match(/\.(vue|((c|m)?j|t)sx?)$/g) || query.macro || query.nuxt_component) { return } + if (!SUPPORTED_FILES_RE.test(pathname) || query.macro || query.nuxt_component) { return } if (!islands.some(c => c.filePath === pathname)) { if (options.shouldInline === false || (typeof options.shouldInline === 'function' && !options.shouldInline(id))) { return } diff --git a/packages/webpack/src/plugins/vue/server.ts b/packages/webpack/src/plugins/vue/server.ts index 69028f65fd..ad6619a759 100644 --- a/packages/webpack/src/plugins/vue/server.ts +++ b/packages/webpack/src/plugins/vue/server.ts @@ -6,6 +6,8 @@ export interface VueSSRServerPluginOptions { filename: string } +const JS_MAP_RE = /\.js\.map$/ + export default class VueSSRServerPlugin { options: VueSSRServerPluginOptions @@ -61,7 +63,7 @@ export default class VueSSRServerPlugin { } else { bundle.files[asset.name] = asset.name } - } else if (asset.name.match(/\.js\.map$/)) { + } else if (JS_MAP_RE.test(asset.name)) { bundle.maps[asset.name.replace(/\.map$/, '')] = asset.name } else { // Do not emit non-js assets for server