2023-04-28 09:14:42 +00:00
|
|
|
import { isIgnored } from '@nuxt/kit'
|
|
|
|
import type { Nuxt } from 'nuxt/schema'
|
|
|
|
import type { Import } from 'unimport'
|
|
|
|
import { createUnimport } from 'unimport'
|
|
|
|
import { createUnplugin } from 'unplugin'
|
|
|
|
import { parseURL } from 'ufo'
|
|
|
|
import { parseQuery } from 'vue-router'
|
|
|
|
import type { getComponentsT } from './module'
|
|
|
|
|
|
|
|
export function createTransformPlugin (nuxt: Nuxt, getComponents: getComponentsT, mode: 'client' | 'server' | 'all') {
|
|
|
|
const componentUnimport = createUnimport({
|
|
|
|
imports: [
|
|
|
|
{
|
|
|
|
name: 'componentNames',
|
|
|
|
from: '#build/component-names'
|
|
|
|
}
|
|
|
|
],
|
|
|
|
virtualImports: ['#components']
|
|
|
|
})
|
|
|
|
|
|
|
|
function getComponentsImports (): Import[] {
|
|
|
|
const components = getComponents(mode)
|
|
|
|
return components.flatMap((c): Import[] => {
|
2023-04-30 09:08:08 +00:00
|
|
|
const withMode = (mode: string | undefined) => mode
|
|
|
|
? `${c.filePath}${c.filePath.includes('?') ? '&' : '?'}nuxt_component=${mode}`
|
|
|
|
: c.filePath
|
|
|
|
|
2023-04-28 09:14:42 +00:00
|
|
|
return [
|
|
|
|
{
|
|
|
|
as: c.pascalName,
|
2023-04-30 09:08:08 +00:00
|
|
|
from: withMode(c.mode === 'client' ? 'client' : undefined),
|
2023-04-28 09:14:42 +00:00
|
|
|
name: 'default'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
as: 'Lazy' + c.pascalName,
|
2023-04-30 09:08:08 +00:00
|
|
|
from: withMode([c.mode === 'client' ? 'client' : '', 'async'].filter(Boolean).join(',')),
|
2023-04-28 09:14:42 +00:00
|
|
|
name: 'default'
|
|
|
|
}
|
|
|
|
]
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return createUnplugin(() => ({
|
|
|
|
name: 'nuxt:components:imports',
|
|
|
|
transformInclude (id) {
|
|
|
|
return !isIgnored(id)
|
|
|
|
},
|
|
|
|
async transform (code, id) {
|
|
|
|
// Virtual component wrapper
|
2023-04-30 09:08:08 +00:00
|
|
|
if (id.match(/[?&]nuxt_component=/)) {
|
2023-04-28 09:14:42 +00:00
|
|
|
const { search } = parseURL(id)
|
|
|
|
const query = parseQuery(search)
|
2023-04-30 09:08:08 +00:00
|
|
|
const mode = query.nuxt_component
|
2023-04-28 09:14:42 +00:00
|
|
|
const bare = id.replace(/\?.*/, '')
|
|
|
|
if (mode === 'async') {
|
|
|
|
return [
|
|
|
|
'import { defineAsyncComponent } from "vue"',
|
|
|
|
`export default defineAsyncComponent(() => import(${JSON.stringify(bare)}).then(r => r.default))`
|
|
|
|
].join('\n')
|
|
|
|
} else if (mode === 'client') {
|
|
|
|
return [
|
|
|
|
`import __component from ${JSON.stringify(bare)}`,
|
|
|
|
'import { createClientOnly } from "#app/components/client-only"',
|
|
|
|
'export default createClientOnly(__component)'
|
|
|
|
].join('\n')
|
|
|
|
} else if (mode === 'client,async') {
|
|
|
|
return [
|
|
|
|
'import { defineAsyncComponent } from "vue"',
|
|
|
|
'import { createClientOnly } from "#app/components/client-only"',
|
|
|
|
`export default defineAsyncComponent(() => import(${JSON.stringify(bare)}).then(r => createClientOnly(r.default)))`
|
|
|
|
].join('\n')
|
|
|
|
} else {
|
|
|
|
throw new Error(`Unknown component mode: ${mode}, this might be an internal bug of Nuxt.`)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!code.includes('#components')) {
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
componentUnimport.modifyDynamicImports((imports) => {
|
|
|
|
imports.length = 0
|
|
|
|
imports.push(...getComponentsImports())
|
|
|
|
return imports
|
|
|
|
})
|
|
|
|
|
|
|
|
const result = await componentUnimport.injectImports(code, id, { autoImport: false, transformVirtualImports: true })
|
|
|
|
if (!result) {
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
code: result.code,
|
|
|
|
map: nuxt.options.sourcemap
|
|
|
|
? result.s.generateMap({ hires: true })
|
|
|
|
: undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}))
|
|
|
|
}
|