feat(kit): add updateTemplates utility (#8413)

This commit is contained in:
Daniel Roe 2022-10-24 09:53:02 +01:00 committed by GitHub
parent 708460ddc8
commit 5a88510cb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 62 additions and 29 deletions

View File

@ -68,6 +68,7 @@ description: Nuxt Kit provides composable utilities to help interacting with Nux
[source code](https://github.com/nuxt/framework/blob/main/packages/kit/src/template.ts)
- `addTemplate(templateOptions)`
- `updateTemplates({ filter?: ResolvedNuxtTemplate => boolean })`
### Nitro

View File

@ -71,3 +71,12 @@ export function normalizeTemplate (template: NuxtTemplate<any> | string): Resolv
return template as ResolvedNuxtTemplate<any>
}
/**
* Trigger rebuilding Nuxt templates
*
* You can pass a filter within the options to selectively regenerate a subset of templates.
*/
export function updateTemplates (options?: { filter?: (template: ResolvedNuxtTemplate<any>) => boolean }) {
return useNuxt().hooks.callHook('builder:generateApp', options)
}

View File

@ -1,6 +1,6 @@
import { statSync } from 'node:fs'
import { relative, resolve } from 'pathe'
import { defineNuxtModule, resolveAlias, addTemplate, addPluginTemplate } from '@nuxt/kit'
import { defineNuxtModule, resolveAlias, addTemplate, addPluginTemplate, updateTemplates } from '@nuxt/kit'
import type { Component, ComponentsDir, ComponentsOptions } from '@nuxt/schema'
import { distDir } from '../dirs'
import { componentsPluginTemplate, componentsTemplate, componentsTypeTemplate } from './templates'
@ -122,12 +122,12 @@ export default defineNuxtModule<ComponentsOptions>({
nuxt.hook('vite:extendConfig', (config, { isClient }) => {
const mode = isClient ? 'client' : 'server'
;(config.resolve!.alias as any)['#components'] = resolve(nuxt.options.buildDir, `components.${mode}.mjs`)
; (config.resolve!.alias as any)['#components'] = resolve(nuxt.options.buildDir, `components.${mode}.mjs`)
})
nuxt.hook('webpack:config', (configs) => {
for (const config of configs) {
const mode = config.name === 'server' ? 'server' : 'client'
;(config.resolve!.alias as any)['#components'] = resolve(nuxt.options.buildDir, `components.${mode}.mjs`)
; (config.resolve!.alias as any)['#components'] = resolve(nuxt.options.buildDir, `components.${mode}.mjs`)
}
})
@ -173,7 +173,14 @@ export default defineNuxtModule<ComponentsOptions>({
}
const fPath = resolve(nuxt.options.srcDir, path)
if (componentDirs.find(dir => fPath.startsWith(dir.path))) {
await nuxt.callHook('builder:generateApp')
await updateTemplates({
filter: template => [
'components.plugin.mjs',
'components.d.ts',
'components.server.mjs',
'components.client.mjs'
].includes(template.filename)
})
}
})

View File

@ -1,7 +1,7 @@
import { promises as fsp } from 'node:fs'
import { dirname, resolve } from 'pathe'
import defu from 'defu'
import type { Nuxt, NuxtApp, NuxtPlugin, NuxtTemplate } from '@nuxt/schema'
import type { Nuxt, NuxtApp, NuxtPlugin, NuxtTemplate, ResolvedNuxtTemplate } from '@nuxt/schema'
import { findPath, resolveFiles, normalizePlugin, normalizeTemplate, compileTemplate, templateUtils, tryResolveModule, resolvePath, resolveAlias } from '@nuxt/kit'
import * as defaultTemplates from './templates'
@ -16,7 +16,7 @@ export function createApp (nuxt: Nuxt, options: Partial<NuxtApp> = {}): NuxtApp
} as unknown as NuxtApp) as NuxtApp
}
export async function generateApp (nuxt: Nuxt, app: NuxtApp) {
export async function generateApp (nuxt: Nuxt, app: NuxtApp, options: { filter?: (template: ResolvedNuxtTemplate<any>) => boolean } = {}) {
// Resolve app
await resolveApp(nuxt, app)
@ -31,25 +31,27 @@ export async function generateApp (nuxt: Nuxt, app: NuxtApp) {
// Compile templates into vfs
const templateContext = { utils: templateUtils, nuxt, app }
await Promise.all(app.templates.map(async (template) => {
const contents = await compileTemplate(template, templateContext)
await Promise.all((app.templates as Array<ReturnType<typeof normalizeTemplate>>)
.filter(template => !options.filter || options.filter(template))
.map(async (template) => {
const contents = await compileTemplate(template, templateContext)
const fullPath = template.dst || resolve(nuxt.options.buildDir, template.filename!)
nuxt.vfs[fullPath] = contents
const fullPath = template.dst || resolve(nuxt.options.buildDir, template.filename!)
nuxt.vfs[fullPath] = contents
const aliasPath = '#build/' + template.filename!.replace(/\.\w+$/, '')
nuxt.vfs[aliasPath] = contents
const aliasPath = '#build/' + template.filename!.replace(/\.\w+$/, '')
nuxt.vfs[aliasPath] = contents
// In case a non-normalized absolute path is called for on Windows
if (process.platform === 'win32') {
nuxt.vfs[fullPath.replace(/\//g, '\\')] = contents
}
// In case a non-normalized absolute path is called for on Windows
if (process.platform === 'win32') {
nuxt.vfs[fullPath.replace(/\//g, '\\')] = contents
}
if (template.write) {
await fsp.mkdir(dirname(fullPath), { recursive: true })
await fsp.writeFile(fullPath, contents, 'utf8')
}
}))
if (template.write) {
await fsp.mkdir(dirname(fullPath), { recursive: true })
await fsp.writeFile(fullPath, contents, 'utf8')
}
}))
await nuxt.callHook('app:templatesGenerated', app)
}

View File

@ -23,7 +23,11 @@ export async function build (nuxt: Nuxt) {
await generateApp()
}
})
nuxt.hook('builder:generateApp', generateApp)
nuxt.hook('builder:generateApp', (options) => {
// Bypass debounce if we are selectively invalidating templates
if (options) { return _generateApp(nuxt, app, options) }
return generateApp()
})
}
await nuxt.callHook('build:before', { nuxt }, nuxt.options.build)

View File

@ -1,4 +1,4 @@
import { addVitePlugin, addWebpackPlugin, defineNuxtModule, addTemplate, resolveAlias, useNuxt, addPluginTemplate, logger } from '@nuxt/kit'
import { addVitePlugin, addWebpackPlugin, defineNuxtModule, addTemplate, resolveAlias, useNuxt, addPluginTemplate, logger, updateTemplates } from '@nuxt/kit'
import { isAbsolute, join, relative, resolve, normalize } from 'pathe'
import { createUnimport, Import, scanDirExports, toImports, Unimport } from 'unimport'
import { ImportsOptions, ImportPresetWithDeprecation } from '@nuxt/schema'
@ -77,7 +77,6 @@ export default defineNuxtModule<Partial<ImportsOptions>>({
nuxt.options.alias['#imports'] = join(nuxt.options.buildDir, 'imports')
// Transpile and injection
// @ts-ignore temporary disabled due to #746
if (nuxt.options.dev && options.global) {
// Add all imports to globalThis in development mode
addPluginTemplate({
@ -117,10 +116,17 @@ export default defineNuxtModule<Partial<ImportsOptions>>({
})
// Watch composables/ directory
const templates = [
'types/imports.d.ts',
'imports.d.ts',
'imports.mjs'
]
nuxt.hook('builder:watch', async (_, path) => {
const _resolved = resolve(nuxt.options.srcDir, path)
if (composablesDirs.find(dir => _resolved.startsWith(dir))) {
await nuxt.callHook('builder:generateApp')
await updateTemplates({
filter: template => templates.includes(template.filename)
})
}
})

View File

@ -1,5 +1,5 @@
import { existsSync } from 'node:fs'
import { defineNuxtModule, addTemplate, addPlugin, addVitePlugin, addWebpackPlugin, findPath, addComponent } from '@nuxt/kit'
import { defineNuxtModule, addTemplate, addPlugin, addVitePlugin, addWebpackPlugin, findPath, addComponent, updateTemplates } from '@nuxt/kit'
import { relative, resolve } from 'pathe'
import { genString, genImport, genObjectFromRawEntries } from 'knitwork'
import escapeRE from 'escape-string-regexp'
@ -48,7 +48,7 @@ export default defineNuxtModule({
const pathPattern = new RegExp(`(^|\\/)(${dirs.map(escapeRE).join('|')})/`)
if (event !== 'change' && path.match(pathPattern)) {
await nuxt.callHook('builder:generateApp')
await updateTemplates()
}
})

View File

@ -6,7 +6,7 @@ import type { InlineConfig as ViteInlineConfig, ViteDevServer } from 'vite'
import type { Manifest } from 'vue-bundle-renderer'
import type { EventHandler } from 'h3'
import type { ModuleContainer } from './module'
import type { NuxtTemplate, Nuxt, NuxtApp } from './nuxt'
import type { NuxtTemplate, Nuxt, NuxtApp, ResolvedNuxtTemplate } from './nuxt'
import type { Preset as ImportPreset, Import } from 'unimport'
import type { NuxtConfig, NuxtOptions } from './config'
import type { Nitro, NitroConfig } from 'nitropack'
@ -66,6 +66,10 @@ export interface ImportPresetWithDeprecation extends ImportPreset {
names?: string[]
}
export interface GenerateAppOptions {
filter?: (template: ResolvedNuxtTemplate<any>) => boolean
}
export interface NuxtHooks {
// Kit
'kit:compatibility': (compatibility: NuxtCompatibility, issues: NuxtCompatibilityIssues) => HookResult
@ -74,7 +78,7 @@ export interface NuxtHooks {
'app:resolve': (app: NuxtApp) => HookResult
'app:templates': (app: NuxtApp) => HookResult
'app:templatesGenerated': (app: NuxtApp) => HookResult
'builder:generateApp': () => HookResult
'builder:generateApp': (options?: GenerateAppOptions) => HookResult
'pages:extend': (pages: NuxtPage[]) => HookResult
'build:manifest': (manifest: Manifest) => HookResult
'server:devHandler': (handler: EventHandler) => HookResult