feat(kit): `addComponent` utility (#1579)

This commit is contained in:
pooya parsa 2021-11-02 12:27:25 +01:00 committed by GitHub
parent 266578b76e
commit efe1fea1d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 10 deletions

View File

@ -2,6 +2,7 @@ import { existsSync, promises as fsp } from 'fs'
import { basename, extname, parse, resolve } from 'pathe'
import lodashTemplate from 'lodash.template'
import hash from 'hash-sum'
import { pascalCase, camelCase, kebabCase } from 'scule'
import type { WebpackPluginInstance, Configuration as WebpackConfig } from 'webpack'
import type { Plugin as VitePlugin, UserConfig as ViteConfig } from 'vite'
import { camelCase } from 'scule'
@ -10,7 +11,7 @@ import { NuxtCompatibilityConstraints, NuxtCompatibilityIssues } from '../types/
import { Nuxt } from '../types/nuxt'
import { useNuxt } from '../nuxt'
import type { NuxtTemplate, NuxtPlugin, NuxtPluginTemplate } from '../types/nuxt'
import type { ComponentsDir } from '../types/components'
import type { ComponentsDir, Component } from '../types/components'
/**
* Renders given template using lodash template during build into the project buildDir
@ -302,6 +303,52 @@ export function addComponentsDir (dir: ComponentsDir) {
nuxt.hook('components:dirs', (dirs) => { dirs.push(dir) })
}
export type AddComponentOptions = { name: string, filePath: string } & Partial<Exclude<Component,
'shortPath' | 'async' | 'level' | 'import' | 'asyncImport'
>>
/**
* Register a directory to be scanned for components and imported only when used.
*
* Requires Nuxt 2.13+
*/
export function addComponent (opts: AddComponentOptions) {
const nuxt = useNuxt()
ensureNuxtCompatibility({ nuxt: '>=2.13' }, nuxt)
nuxt.options.components = nuxt.options.components || []
// Apply defaults
const component: Component = {
export: opts.export || 'default',
chunkName: 'components/' + kebabCase(opts.name),
global: opts.global ?? false,
kebabName: kebabCase(opts.name || ''),
pascalName: pascalCase(opts.name || ''),
prefetch: false,
preload: false,
// Nuxt 2 support
shortPath: opts.filePath,
async: false,
level: 0,
asyncImport: `() => import('${opts.filePath}').then(r => r['${opts.export || 'default'}'])`,
import: `require('${opts.filePath}')['${opts.export || 'default'}']`,
...opts
}
nuxt.hook('components:extend', (components: Component[]) => {
const existingComponent = components.find(c => c.pascalName === component.pascalName || c.kebabName === component.kebabName)
if (existingComponent) {
const name = existingComponent.pascalName || existingComponent.kebabName
console.warn(`Overriding ${name} component.`)
Object.assign(existingComponent, component)
} else {
components.push(component)
}
})
}
const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"{(.+)}"/g, '$1')
const importName = (src: string) => `${camelCase(basename(src, extname(src))).replace(/[^a-zA-Z?\d\s:]/g, '')}_${hash(src)}`

View File

@ -1,5 +1,5 @@
/* eslint-disable no-use-before-define */
import { getCurrentInstance, reactive, defineAsyncComponent } from 'vue'
import { getCurrentInstance, reactive } from 'vue'
import type { App, VNode } from 'vue'
import { createHooks, Hookable } from 'hookable'
import { legacyPlugin, LegacyContext } from './legacy'
@ -99,12 +99,6 @@ export function createNuxtApp (options: CreateOptions) {
nuxtApp.ssrContext.nuxt = nuxtApp
}
// (temporary) Expose NuxtWelcome component in dev
if (process.dev) {
// @ts-ignore
nuxtApp.vueApp.component('NuxtWelcome', defineAsyncComponent(() => import('./components/nuxt-welcome.vue')))
}
if (process.server) {
// Expose to server renderer to create window.__NUXT__
nuxtApp.ssrContext = nuxtApp.ssrContext || {}

View File

@ -1,6 +1,6 @@
import { resolve } from 'pathe'
import { createHooks } from 'hookable'
import { loadNuxtConfig, LoadNuxtOptions, Nuxt, NuxtOptions, NuxtConfig, nuxtCtx, installModule, ModuleContainer, NuxtHooks } from '@nuxt/kit'
import { loadNuxtConfig, LoadNuxtOptions, Nuxt, NuxtOptions, NuxtConfig, nuxtCtx, installModule, ModuleContainer, NuxtHooks, addComponent } from '@nuxt/kit'
import pagesModule from '../pages/module'
import metaModule from '../meta/module'
import componentsModule from '../components/module'
@ -52,6 +52,12 @@ async function initNuxt (nuxt: Nuxt) {
...nuxt.options._modules
]
// Add <NuxtWelcome>
addComponent({
name: 'NuxtWelcome',
filePath: resolve(nuxt.options.appDir, 'components/nuxt-welcome.vue')
})
for (const m of modulesToInstall) {
await installModule(nuxt, m)
}
@ -66,7 +72,7 @@ async function initNuxt (nuxt: Nuxt) {
export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
const options = await loadNuxtConfig(opts)
// Temp
// Temporary until finding better placement for each
options.appDir = options.alias['#app'] = resolve(distDir, 'app')
options._majorVersion = 3
options.buildModules.push(pagesModule, metaModule, componentsModule, autoImportsModule)