perf(nuxt): use .test and hoist regexps where possible (#21011)

This commit is contained in:
Daniel Roe 2023-05-22 21:25:42 +01:00 committed by GitHub
parent f94984e5cb
commit c37ebab1ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 39 additions and 19 deletions

View File

@ -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)$/

View File

@ -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)

View File

@ -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'] })

View File

@ -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

View File

@ -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<Nuxt> {
return nuxt
}
const RESTART_RE = /^(app|error|app\.config)\.(js|ts|mjs|jsx|tsx|vue)$/i

View File

@ -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)

View File

@ -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)

View File

@ -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<ImportsOptions>, 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
}

View File

@ -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)

View File

@ -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)

View File

@ -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 }

View File

@ -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<string, { files: string[], inBundle: boolean }> = {}
const idRefMap: Record<string, string> = {}
@ -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 }

View File

@ -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