mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
feat(nuxt3): support lazy and custom-resolved components (#3814)
This commit is contained in:
parent
7458dd1aa6
commit
29078bba74
@ -47,6 +47,39 @@ If you have a component in nested directories such as:
|
||||
For clarity, we recommend that the component's file name matches its name. (So, in the example above, you could rename `Button.vue` to be `BaseFooButton.vue`.)
|
||||
::
|
||||
|
||||
## Dynamic components
|
||||
|
||||
If you want to use the Vue `<component :is="someComputedComponent">` syntax, then you will need to use the `resolveComponent` helper provided by Vue.
|
||||
|
||||
For example:
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<component :is="clickable ? MyButton : 'div'" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const MyButton = resolveComponent('MyButton')
|
||||
</script>
|
||||
```
|
||||
|
||||
Alternatively, though not recommended, you can register all your components globally, which will create async chunks for all your components and make them available throughout your application.
|
||||
|
||||
```diff
|
||||
import { defineNuxtConfig } from 'nuxt3'
|
||||
|
||||
export default defineNuxtConfig({
|
||||
components: {
|
||||
+ global: true,
|
||||
+ dirs: ['~/components']
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
::alert{type=info}
|
||||
The `global` option can also be set per component directory.
|
||||
::
|
||||
|
||||
## Dynamic Imports
|
||||
|
||||
To dynamically import a component (also known as lazy-loading a component) all you need to do is add the `Lazy` prefix to the component's name.
|
||||
|
@ -104,6 +104,7 @@ export const vuePreset = defineUnimportPreset({
|
||||
// Component
|
||||
'defineComponent',
|
||||
'defineAsyncComponent',
|
||||
'resolveComponent',
|
||||
'getCurrentInstance',
|
||||
'h',
|
||||
'inject',
|
||||
|
@ -2,7 +2,7 @@ import { pathToFileURL } from 'url'
|
||||
import { createUnplugin } from 'unplugin'
|
||||
import { parseQuery, parseURL } from 'ufo'
|
||||
import { Component } from '@nuxt/schema'
|
||||
import { genImport } from 'knitwork'
|
||||
import { genDynamicImport, genImport } from 'knitwork'
|
||||
import MagicString from 'magic-string'
|
||||
import { pascalCase } from 'scule'
|
||||
|
||||
@ -37,13 +37,19 @@ function transform (code: string, id: string, components: Component[]) {
|
||||
const s = new MagicString(code)
|
||||
|
||||
// replace `_resolveComponent("...")` to direct import
|
||||
s.replace(/ _resolveComponent\("(.*?)"\)/g, (full, name) => {
|
||||
s.replace(/(?<=[ (])_?resolveComponent\(["'](lazy-|Lazy)?([^'"]*?)["']\)/g, (full, lazy, name) => {
|
||||
const component = findComponent(components, name)
|
||||
if (component) {
|
||||
const identifier = map.get(component) || `__nuxt_component_${num++}`
|
||||
map.set(component, identifier)
|
||||
imports.add(genImport(component.filePath, [{ name: component.export, as: identifier }]))
|
||||
return ` ${identifier}`
|
||||
if (lazy) {
|
||||
// Nuxt will auto-import `defineAsyncComponent` for us
|
||||
imports.add(`const ${identifier}_lazy = defineAsyncComponent(${genDynamicImport(component.filePath)})`)
|
||||
return `${identifier}_lazy`
|
||||
} else {
|
||||
imports.add(genImport(component.filePath, [{ name: component.export, as: identifier }]))
|
||||
return identifier
|
||||
}
|
||||
}
|
||||
// no matched
|
||||
return full
|
||||
|
@ -51,6 +51,7 @@ export const componentsTypeTemplate = {
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
${options.components.map(c => ` '${c.pascalName}': typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(join(options.buildDir, 'types'), c.filePath) : c.filePath, { wrapper: false })}['${c.export}']`).join(',\n')}
|
||||
${options.components.map(c => ` 'Lazy${c.pascalName}': typeof ${genDynamicImport(isAbsolute(c.filePath) ? relative(join(options.buildDir, 'types'), c.filePath) : c.filePath, { wrapper: false })}['${c.export}']`).join(',\n')}
|
||||
}
|
||||
}
|
||||
export {}
|
||||
|
@ -9,6 +9,8 @@ export default {
|
||||
* @see [Nuxt 3](https://v3.nuxtjs.org/docs/directory-structure/components) and
|
||||
* [Nuxt 2](https://nuxtjs.org/docs/directory-structure/components/) documentation
|
||||
* @type {boolean | typeof import('../src/types/components').ComponentsOptions | typeof import('../src/types/components').ComponentsOptions['dirs']}
|
||||
* @version 2
|
||||
* @version 3
|
||||
*/
|
||||
components: {
|
||||
$resolve: (val, get) => {
|
||||
@ -27,6 +29,7 @@ export default {
|
||||
*
|
||||
* @see [Nuxt 3 documentation](https://v3.nuxtjs.org/docs/directory-structure/composables)
|
||||
* @type {typeof import('../src/types/imports').AutoImportsOptions}
|
||||
* @version 3
|
||||
*/
|
||||
autoImports: {
|
||||
global: false,
|
||||
|
Loading…
Reference in New Issue
Block a user