refactor(components): use inline templates (#555)

This commit is contained in:
Xin Du (Clark) 2021-09-23 18:57:37 +01:00 committed by GitHub
parent cf3f564635
commit c4e46881cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 42 deletions

View File

@ -9,7 +9,6 @@ export default defineBuildConfig({
{ input: 'src/app/', outDir: 'dist/app/' },
// Runtime dirs
...[
'components',
'meta',
'pages'
].map(name => ({ input: `src/${name}/runtime/`, outDir: `dist/${name}/runtime`, format: 'esm' } as BuildEntry))

View File

@ -1,12 +1,11 @@
import type { Nuxt, NuxtApp } from '@nuxt/kit'
import * as templateUtils from '../core/template.utils'
import { importName, importSources } from '../core/template.utils'
type TemplateContext = {
nuxt: Nuxt;
app: NuxtApp;
utils: typeof templateUtils
}
export const appTemplate = {
@ -26,11 +25,11 @@ export const cssTemplate = {
export const clientPluginTemplate = {
filename: 'plugins/client.mjs',
getContents (ctx: TemplateContext) {
const { app, utils } = ctx
const { app } = ctx
return [
utils.importSources(app.plugins.filter(p => !p.mode || p.mode !== 'server').map(p => p.src)),
importSources(app.plugins.filter(p => !p.mode || p.mode !== 'server').map(p => p.src)),
'export default [',
app.plugins.filter(p => !p.mode || p.mode !== 'server').map(p => utils.importName(p.src)).join(',\n '),
app.plugins.filter(p => !p.mode || p.mode !== 'server').map(p => importName(p.src)).join(',\n '),
']'
].join('\n')
}
@ -39,13 +38,13 @@ export const clientPluginTemplate = {
export const serverPluginTemplate = {
filename: 'plugins/server.mjs',
getContents (ctx: TemplateContext) {
const { app, utils } = ctx
const { app } = ctx
return [
"import preload from '#app/plugins/preload.server'",
utils.importSources(app.plugins.filter(p => !p.mode || p.mode !== 'client').map(p => p.src)),
importSources(app.plugins.filter(p => !p.mode || p.mode !== 'client').map(p => p.src)),
'export default [',
' preload,',
app.plugins.filter(p => !p.mode || p.mode !== 'client').map(p => utils.importName(p.src)).join(',\n '),
app.plugins.filter(p => !p.mode || p.mode !== 'client').map(p => importName(p.src)).join(',\n '),
']'
].join('\n')
}

View File

@ -1,7 +1,7 @@
import { statSync } from 'fs'
import { resolve, relative } from 'upath'
import { resolve } from 'upath'
import { defineNuxtModule, resolveAlias, addVitePlugin, addWebpackPlugin } from '@nuxt/kit'
import { distDir } from '../dirs'
import { componentsTemplate, componentsTypeTemplate } from './templates'
import { scanComponents } from './scan'
import type { Component, ComponentsDir } from './types'
import { loaderPlugin } from './loader'
@ -66,19 +66,13 @@ export default defineNuxtModule({
}
app.templates.push({
filename: 'components.mjs',
src: resolve(distDir, 'components/runtime/components.tmpl.mjs'),
...componentsTemplate,
options: { components }
})
app.templates.push({
filename: 'components.d.ts',
write: true,
getContents: () => `// Generated by components discovery
declare module 'vue' {
export interface GlobalComponents {
${components.map(c => ` '${c.pascalName}': typeof import('${relative(nuxt.options.buildDir, c.filePath)}')['${c.export}']`).join(',\n')}
}\n}\n\nexport {}`
...componentsTypeTemplate,
options: { components, buildDir: nuxt.options.buildDir }
})
app.plugins.push({ src: '#build/components' })

View File

@ -1,22 +0,0 @@
import { defineAsyncComponent } from 'vue'
const components = {
<%= components.map(c => {
const exp = c.export === 'default' ? `c.default || c` : `c['${c.export}']`
const magicComments = [
`webpackChunkName: "${c.chunkName}"`,
c.prefetch === true || typeof c.prefetch === 'number' ? `webpackPrefetch: ${c.prefetch}` : false,
c.preload === true || typeof c.preload === 'number' ? `webpackPreload: ${c.preload}` : false,
].filter(Boolean).join(', ')
return ` '${c.pascalName}': defineAsyncComponent(() => import('${c.filePath}' /* ${magicComments} */).then(c => ${exp}))`
}).join(',\n') %>
}
export default function (nuxt) {
for (const name in components) {
nuxt.app.component(name, components[name])
nuxt.app.component('Lazy' + name, components[name])
}
}

View File

@ -0,0 +1,61 @@
import { relative } from 'upath'
import type { Component } from './types'
export type ComponentsTemplateOptions = {
buildDir?: string
components: Component[]
}
export type ImportMagicCommentsOptions = {
chunkName:string
prefetch?: boolean | number
preload?: boolean | number
}
const createImportMagicComments = (options: ImportMagicCommentsOptions) => {
const { chunkName, prefetch, preload } = options
return [
`webpackChunkName: "${chunkName}"`,
prefetch === true || typeof prefetch === 'number' ? `webpackPrefetch: ${prefetch}` : false,
preload === true || typeof preload === 'number' ? `webpackPreload: ${preload}` : false
].filter(Boolean).join(', ')
}
export const componentsTemplate = {
filename: 'components.mjs',
getContents (options: ComponentsTemplateOptions) {
return `import { defineAsyncComponent } from 'vue'
const components = {
${options.components.map((c) => {
const exp = c.export === 'default' ? 'c.default || c' : `c['${c.export}']`
const magicComments = createImportMagicComments(c)
return ` '${c.pascalName}': defineAsyncComponent(() => import('${c.filePath}' /* ${magicComments} */).then(c => ${exp}))`
}).join(',\n')}
}
export default function (nuxt) {
for (const name in components) {
nuxt.app.component(name, components[name])
nuxt.app.component('Lazy' + name, components[name])
}
}
`
}
}
export const componentsTypeTemplate = {
filename: 'components.d.ts',
write: true,
getContents: (options: ComponentsTemplateOptions) => `// Generated by components discovery
declare module 'vue' {
export interface GlobalComponents {
${options.components.map(c => ` '${c.pascalName}': typeof import('${relative(options.buildDir, c.filePath)}')['${c.export}']`).join(',\n')}
}
export {}
}`
}