refactor(nuxt): rework and use isJS and isVue utilities consistently (#20344)

This commit is contained in:
Daniel Roe 2023-04-19 19:17:36 +01:00 committed by GitHub
parent 5febd46d23
commit c7be5b4ec6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 70 additions and 103 deletions

View File

@ -3,7 +3,7 @@ import type { ComponentsOptions } from '@nuxt/schema'
import MagicString from 'magic-string' import MagicString from 'magic-string'
import { isAbsolute, relative } from 'pathe' import { isAbsolute, relative } from 'pathe'
import { hash } from 'ohash' import { hash } from 'ohash'
import { isVueTemplate } from './helpers' import { isVue } from '../core/utils'
interface LoaderOptions { interface LoaderOptions {
sourcemap?: boolean sourcemap?: boolean
transform?: ComponentsOptions['transform'], transform?: ComponentsOptions['transform'],
@ -25,7 +25,7 @@ export const clientFallbackAutoIdPlugin = createUnplugin((options: LoaderOptions
if (include.some(pattern => id.match(pattern))) { if (include.some(pattern => id.match(pattern))) {
return true return true
} }
return isVueTemplate(id) return isVue(id, { type: ['template'] })
}, },
transform (code, id) { transform (code, id) {
if (!CLIENT_FALLBACK_RE.test(code)) { return } if (!CLIENT_FALLBACK_RE.test(code)) { return }

View File

@ -1,29 +0,0 @@
import { pathToFileURL } from 'node:url'
import { parseQuery, parseURL } from 'ufo'
export function isVueTemplate (id: string) {
// Bare `.vue` file (in Vite)
if (id.endsWith('.vue')) {
return true
}
const { search } = parseURL(decodeURIComponent(pathToFileURL(id).href))
if (!search) {
return false
}
const query = parseQuery(search)
// Macro
if (query.macro) {
return true
}
// Non-Vue or Styles
if (!('vue' in query) || query.type === 'style') {
return false
}
// Query `?vue&type=template` (in Webpack or external template)
return true
}

View File

@ -6,7 +6,7 @@ import { resolve } from 'pathe'
import type { Component, ComponentsOptions } from 'nuxt/schema' import type { Component, ComponentsOptions } from 'nuxt/schema'
import { distDir } from '../dirs' import { distDir } from '../dirs'
import { isVueTemplate } from './helpers' import { isVue } from '../core/utils'
interface LoaderOptions { interface LoaderOptions {
getComponents (): Component[] getComponents (): Component[]
@ -31,7 +31,7 @@ export const loaderPlugin = createUnplugin((options: LoaderOptions) => {
if (include.some(pattern => id.match(pattern))) { if (include.some(pattern => id.match(pattern))) {
return true return true
} }
return isVueTemplate(id) return isVue(id, { type: ['template', 'script'] })
}, },
transform (code) { transform (code) {
const components = options.getComponents() const components = options.getComponents()

View File

@ -1,8 +1,7 @@
import { pathToFileURL } from 'node:url'
import { stripLiteral } from 'strip-literal' import { stripLiteral } from 'strip-literal'
import { parseQuery, parseURL } from 'ufo'
import MagicString from 'magic-string' import MagicString from 'magic-string'
import { createUnplugin } from 'unplugin' import { createUnplugin } from 'unplugin'
import { isJS, isVue } from '../utils'
type ImportPath = string type ImportPath = string
@ -22,18 +21,7 @@ export const TreeShakeComposablesPlugin = createUnplugin((options: TreeShakeComp
name: 'nuxt:tree-shake-composables:transform', name: 'nuxt:tree-shake-composables:transform',
enforce: 'post', enforce: 'post',
transformInclude (id) { transformInclude (id) {
const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href)) return isVue(id, { type: ['script'] }) || isJS(id)
const { type } = parseQuery(search)
// vue files
if (pathname.endsWith('.vue') && (type === 'script' || !search)) {
return true
}
// js files
if (pathname.match(/\.((c|m)?j|t)sx?$/g)) {
return true
}
}, },
transform (code) { transform (code) {
if (!code.match(COMPOSABLE_RE)) { return } if (!code.match(COMPOSABLE_RE)) { return }

View File

@ -1,9 +1,9 @@
import { pathToFileURL } from 'node:url'
import { parseQuery, parseURL } from 'ufo'
import type { TransformerOptions } from 'unctx/transform' import type { TransformerOptions } from 'unctx/transform'
import { createTransformer } from 'unctx/transform' import { createTransformer } from 'unctx/transform'
import { createUnplugin } from 'unplugin' import { createUnplugin } from 'unplugin'
import { isJS, isVue } from '../utils'
const TRANSFORM_MARKER = '/* _processed_nuxt_unctx_transform */\n' const TRANSFORM_MARKER = '/* _processed_nuxt_unctx_transform */\n'
interface UnctxTransformPluginOptions { interface UnctxTransformPluginOptions {
@ -17,22 +17,7 @@ export const UnctxTransformPlugin = createUnplugin((options: UnctxTransformPlugi
name: 'unctx:transform', name: 'unctx:transform',
enforce: 'post', enforce: 'post',
transformInclude (id) { transformInclude (id) {
const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href)) return isVue(id) || isJS(id)
const query = parseQuery(search)
// Vue files
if (
pathname.endsWith('.vue') ||
'macro' in query ||
('vue' in query && (query.type === 'template' || query.type === 'script' || 'setup' in query))
) {
return true
}
// JavaScript files
if (pathname.match(/\.((c|m)?j|t)sx?$/g)) {
return true
}
}, },
transform (code) { transform (code) {
// TODO: needed for webpack - update transform in unctx/unplugin? // TODO: needed for webpack - update transform in unctx/unplugin?

View File

@ -0,0 +1,13 @@
export * from './names'
export * from './plugins'
export function uniqueBy<T, K extends keyof T> (arr: T[], key: K) {
const res: T[] = []
const seen = new Set<T[K]>()
for (const item of arr) {
if (seen.has(item[key])) { continue }
seen.add(item[key])
res.push(item)
}
return res
}

View File

@ -5,17 +5,6 @@ export function getNameFromPath (path: string) {
return kebabCase(basename(path).replace(extname(path), '')).replace(/["']/g, '') return kebabCase(basename(path).replace(extname(path), '')).replace(/["']/g, '')
} }
export function uniqueBy <T, K extends keyof T> (arr: T[], key: K) {
const res: T[] = []
const seen = new Set<T[K]>()
for (const item of arr) {
if (seen.has(item[key])) { continue }
seen.add(item[key])
res.push(item)
}
return res
}
export function hasSuffix (path: string, suffix: string) { export function hasSuffix (path: string, suffix: string) {
return basename(path).replace(extname(path), '').endsWith(suffix) return basename(path).replace(extname(path), '').endsWith(suffix)
} }

View File

@ -0,0 +1,38 @@
import { pathToFileURL } from 'node:url'
import { parseQuery, parseURL } from 'ufo'
export function isVue (id: string, opts: { type?: Array<'template' | 'script' | 'style'> } = {}) {
// Bare `.vue` file (in Vite)
const { search } = parseURL(decodeURIComponent(pathToFileURL(id).href))
if (id.endsWith('.vue') && !search) {
return true
}
if (!search) {
return false
}
const query = parseQuery(search)
// Macro
if (query.macro && (!opts.type || opts.type.includes('script'))) {
return true
}
// Non-Vue or Styles
const type = 'setup' in query ? 'script' : query.type as 'script' | 'template' | 'style'
if (!('vue' in query) || (opts.type && !opts.type.includes(type))) {
return false
}
// Query `?vue&type=template` (in Webpack or external template)
return true
}
const JS_RE = /\.((c|m)?j|t)sx?$/
export function isJS (id: string) {
// JavaScript files
const { pathname } = parseURL(decodeURIComponent(pathToFileURL(id).href))
return JS_RE.test(pathname)
}

View File

@ -1,18 +1,14 @@
import { pathToFileURL } from 'node:url'
import { createUnplugin } from 'unplugin' import { createUnplugin } from 'unplugin'
import { parseQuery, parseURL } from 'ufo'
import type { Unimport } from 'unimport' import type { Unimport } from 'unimport'
import { normalize } from 'pathe' import { normalize } from 'pathe'
import type { ImportsOptions } from 'nuxt/schema' import type { ImportsOptions } from 'nuxt/schema'
import { isJS, isVue } from '../core/utils'
export const TransformPlugin = createUnplugin(({ ctx, options, sourcemap }: { ctx: Unimport, options: Partial<ImportsOptions>, sourcemap?: boolean }) => { export const TransformPlugin = createUnplugin(({ ctx, options, sourcemap }: { ctx: Unimport, options: Partial<ImportsOptions>, sourcemap?: boolean }) => {
return { return {
name: 'nuxt:imports-transform', name: 'nuxt:imports-transform',
enforce: 'post', enforce: 'post',
transformInclude (id) { transformInclude (id) {
const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href))
const query = parseQuery(search)
// Included // Included
if (options.transform?.include?.some(pattern => id.match(pattern))) { if (options.transform?.include?.some(pattern => id.match(pattern))) {
return true return true
@ -23,18 +19,12 @@ export const TransformPlugin = createUnplugin(({ ctx, options, sourcemap }: { ct
} }
// Vue files // Vue files
if ( if (isVue(id, { type: ['script', 'template'] })) {
id.endsWith('.vue') ||
'macro' in query ||
('vue' in query && (query.type === 'template' || query.type === 'script' || 'setup' in query))
) {
return true return true
} }
// JavaScript files // JavaScript files
if (pathname.match(/\.((c|m)?j|t)sx?$/g)) { return isJS(id)
return true
}
}, },
async transform (code, id) { async transform (code, id) {
id = normalize(id) id = normalize(id)

View File

@ -1,8 +1,7 @@
import { pathToFileURL } from 'node:url'
import MagicString from 'magic-string' import MagicString from 'magic-string'
import { parseQuery, parseURL } from 'ufo'
import { createUnplugin } from 'unplugin' import { createUnplugin } from 'unplugin'
import { stripLiteral } from 'strip-literal' import { stripLiteral } from 'strip-literal'
import { isJS, isVue } from '../../../nuxt/src/core/utils/plugins'
export interface PureAnnotationsOptions { export interface PureAnnotationsOptions {
sourcemap: boolean sourcemap: boolean
@ -16,18 +15,7 @@ export const pureAnnotationsPlugin = createUnplugin((options: PureAnnotationsOpt
name: 'nuxt:pure-annotations', name: 'nuxt:pure-annotations',
enforce: 'post', enforce: 'post',
transformInclude (id) { transformInclude (id) {
const { pathname, search } = parseURL(decodeURIComponent(pathToFileURL(id).href)) return isVue(id, { type: ['script'] }) || isJS(id)
const { type } = parseQuery(search)
// vue files
if (pathname.endsWith('.vue') && (type === 'script' || !search)) {
return true
}
// js files
if (pathname.match(/\.((c|m)?j|t)sx?$/g)) {
return true
}
}, },
transform (code) { transform (code) {
if (!FUNCTION_RE_SINGLE.test(code)) { return } if (!FUNCTION_RE_SINGLE.test(code)) { return }

View File

@ -46,6 +46,11 @@ const config = useRuntimeConfig()
const someValue = useState('val', () => 1) const someValue = useState('val', () => 1)
const NestedSugarCounter = resolveComponent('NestedSugarCounter')
if (!NestedSugarCounter) {
throw new Error('Component not found')
}
definePageMeta({ definePageMeta({
alias: '/some-alias', alias: '/some-alias',
other: ref('test'), other: ref('test'),