mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
feat(kit): support templates with getContents()
for nuxt 2 (#587)
This commit is contained in:
parent
337bd3d2b4
commit
7fdcee3252
@ -13,6 +13,7 @@
|
||||
"prepack": "unbuild"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash": "^4.14.173",
|
||||
"unbuild": "latest"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -24,6 +25,7 @@
|
||||
"hash-sum": "^2.0.0",
|
||||
"hookable": "^5.0.0",
|
||||
"jiti": "^1.12.3",
|
||||
"lodash": "^4.17.21",
|
||||
"pathe": "^0.2.0",
|
||||
"rc9": "^1.2.0",
|
||||
"scule": "^0.2.1",
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { promises as fsp } from 'fs'
|
||||
import defu from 'defu'
|
||||
import { applyDefaults } from 'untyped'
|
||||
import { useNuxt, nuxtCtx } from '../nuxt'
|
||||
import type { Nuxt } from '../types/nuxt'
|
||||
import type { Nuxt, NuxtTemplate } from '../types/nuxt'
|
||||
import type { NuxtModule, LegacyNuxtModule, ModuleOptions } from '../types/module'
|
||||
import { compileTemplate, isNuxt2, templateUtils } from './utils'
|
||||
|
||||
/**
|
||||
* Define a Nuxt module, automatically merging defaults with user provided options, installing
|
||||
@ -48,6 +50,39 @@ export function defineNuxtModule<OptionsT extends ModuleOptions> (input: NuxtMod
|
||||
}
|
||||
}
|
||||
|
||||
if (isNuxt2()) {
|
||||
// Support virtual templates with getContents() by writing them to .nuxt directory
|
||||
let virtualTemplates: NuxtTemplate[]
|
||||
nuxt.hook('builder:prepared', (_builder, buildOptions) => {
|
||||
virtualTemplates = []
|
||||
buildOptions.templates.forEach((template, index, arr) => {
|
||||
if (!template.getContents) { return }
|
||||
// Remove template from template array to handle it ourselves
|
||||
arr.splice(index, 1)
|
||||
virtualTemplates.push(template)
|
||||
})
|
||||
})
|
||||
nuxt.hook('build:templates', async (templates) => {
|
||||
const context = {
|
||||
nuxt,
|
||||
utils: templateUtils,
|
||||
app: {
|
||||
dir: nuxt.options.srcDir,
|
||||
extensions: nuxt.options.extensions,
|
||||
plugins: nuxt.options.plugins,
|
||||
templates: [
|
||||
...templates.templatesFiles,
|
||||
...virtualTemplates
|
||||
]
|
||||
}
|
||||
}
|
||||
for await (const template of virtualTemplates) {
|
||||
const contents = await compileTemplate({ ...template, src: '' }, context)
|
||||
await fsp.writeFile(template.dst, contents)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Call setup
|
||||
return mod.setup.call(null, resolvedOptions, nuxt)
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
import fs from 'fs'
|
||||
import { basename, parse, resolve } from 'pathe'
|
||||
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 type { WebpackPluginInstance, Configuration as WebpackConfig } from 'webpack'
|
||||
import type { Plugin as VitePlugin, UserConfig as ViteConfig } from 'vite'
|
||||
import { camelCase } from 'scule'
|
||||
import { useNuxt } from '../nuxt'
|
||||
import type { NuxtTemplate, NuxtPlugin, NuxtPluginTemplate } from '../types/nuxt'
|
||||
|
||||
@ -42,7 +44,7 @@ export function normalizeTemplate (template: NuxtTemplate | string): NuxtTemplat
|
||||
|
||||
// Use src if provided
|
||||
if (template.src) {
|
||||
if (!fs.existsSync(template.src)) {
|
||||
if (!existsSync(template.src)) {
|
||||
throw new Error('Template not found: ' + template.src)
|
||||
}
|
||||
if (!template.filename) {
|
||||
@ -259,3 +261,42 @@ export function addVitePlugin (plugin: VitePlugin, options?: ExtendViteConfigOpt
|
||||
export function isNuxt2 (nuxt?: any) {
|
||||
return (nuxt || useNuxt()).version?.startsWith('v2')
|
||||
}
|
||||
|
||||
export async function compileTemplate (template: NuxtTemplate, ctx: any) {
|
||||
const data = { ...ctx, ...template.options }
|
||||
if (template.src) {
|
||||
try {
|
||||
const srcContents = await fsp.readFile(template.src, 'utf-8')
|
||||
return lodashTemplate(srcContents, {})(data)
|
||||
} catch (err) {
|
||||
console.error('Error compiling template: ', template)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
if (template.getContents) {
|
||||
return template.getContents(data)
|
||||
}
|
||||
throw new Error('Invalid template: ' + JSON.stringify(template))
|
||||
}
|
||||
|
||||
const serialize = data => 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)}`
|
||||
|
||||
const importSources = (sources: string | string[], { lazy = false } = {}) => {
|
||||
if (!Array.isArray(sources)) {
|
||||
sources = [sources]
|
||||
}
|
||||
return sources.map((src) => {
|
||||
if (lazy) {
|
||||
return `const ${importName(src)} = () => import('${src}' /* webpackChunkName: '${src}' */)`
|
||||
}
|
||||
return `import ${importName(src)} from '${src}'`
|
||||
}).join('\n')
|
||||
}
|
||||
|
||||
export const templateUtils = {
|
||||
serialize,
|
||||
importName,
|
||||
importSources
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import type { HookCallback } from 'hookable'
|
||||
import type { Compiler, Configuration, Stats } from 'webpack'
|
||||
import type { NuxtConfig, NuxtOptions } from '..'
|
||||
import type { ModuleContainer } from '../module/container'
|
||||
import { NuxtTemplate } from '../types/nuxt'
|
||||
import { Nuxt, NuxtApp } from './nuxt'
|
||||
|
||||
type HookResult = Promise<void> | void
|
||||
@ -11,13 +12,6 @@ type Builder = any
|
||||
type Generator = any
|
||||
type Server = any
|
||||
|
||||
type TemplateFile = string | {
|
||||
src?: string
|
||||
dst?: string
|
||||
custom?: boolean
|
||||
options?: any
|
||||
}
|
||||
|
||||
type WatchEvent = 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir'
|
||||
interface PreloadFile {
|
||||
asType: 'script' | 'style' | 'font'
|
||||
@ -49,7 +43,7 @@ export interface NuxtHooks extends Record<string, HookCallback> {
|
||||
'builder:extendPlugins': (plugins: NuxtOptions['plugins']) => HookResult
|
||||
'build:templates': (templates: {
|
||||
templateVars: Record<string, any>,
|
||||
templatesFiles: TemplateFile[],
|
||||
templatesFiles: NuxtTemplate[],
|
||||
resolve: (...args: string[]) => string
|
||||
}) => HookResult
|
||||
'build:extendRoutes': (routes: any[], resolve: (...args: string[]) => string) => HookResult
|
||||
|
@ -23,6 +23,8 @@ export interface Nuxt {
|
||||
export interface NuxtTemplate {
|
||||
/** @deprecated filename */
|
||||
fileName?: string
|
||||
/** @deprecated whether template is custom or a nuxt core template */
|
||||
custom?: boolean
|
||||
/** resolved output file path (generated) */
|
||||
dst?: string
|
||||
/** The target filename once the template is copied into the Nuxt buildDir */
|
||||
|
@ -33,7 +33,6 @@
|
||||
"hash-sum": "^2.0.0",
|
||||
"hookable": "^5.0.0",
|
||||
"ignore": "^5.1.8",
|
||||
"lodash": "^4.17.21",
|
||||
"nuxi": "^0.10.0",
|
||||
"ohmyfetch": "^0.3.1",
|
||||
"pathe": "^0.2.0",
|
||||
@ -47,7 +46,6 @@
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^9.0.13",
|
||||
"@types/hash-sum": "^1.0.0",
|
||||
"@types/lodash": "^4.14.173",
|
||||
"unbuild": "latest",
|
||||
"vue-meta": "next"
|
||||
},
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { resolve } from 'pathe'
|
||||
import lodashTemplate from 'lodash/template'
|
||||
import defu from 'defu'
|
||||
import { tryResolvePath, resolveFiles, Nuxt, NuxtApp, NuxtTemplate, normalizePlugin, normalizeTemplate } from '@nuxt/kit'
|
||||
import { readFile, writeFile } from 'fs-extra'
|
||||
import { tryResolvePath, resolveFiles, Nuxt, NuxtApp, normalizePlugin, normalizeTemplate, compileTemplate, templateUtils } from '@nuxt/kit'
|
||||
import { writeFile } from 'fs-extra'
|
||||
|
||||
import * as defaultTemplates from '../app/templates'
|
||||
import * as templateUtils from './template.utils'
|
||||
|
||||
export function createApp (nuxt: Nuxt, options: Partial<NuxtApp> = {}): NuxtApp {
|
||||
return defu(options, {
|
||||
@ -77,20 +75,3 @@ export async function resolveApp (nuxt: Nuxt, app: NuxtApp) {
|
||||
// Extend app
|
||||
await nuxt.callHook('app:resolve', app)
|
||||
}
|
||||
|
||||
async function compileTemplate (template: NuxtTemplate, ctx: any) {
|
||||
const data = { ...ctx, ...template.options }
|
||||
if (template.src) {
|
||||
try {
|
||||
const srcContents = await readFile(template.src, 'utf-8')
|
||||
return lodashTemplate(srcContents, {})(data)
|
||||
} catch (err) {
|
||||
console.error('Error compiling template: ', template)
|
||||
throw err
|
||||
}
|
||||
}
|
||||
if (template.getContents) {
|
||||
return template.getContents(data)
|
||||
}
|
||||
throw new Error('Invalid template: ' + JSON.stringify(template))
|
||||
}
|
||||
|
@ -1485,6 +1485,7 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@nuxt/kit@workspace:packages/kit"
|
||||
dependencies:
|
||||
"@types/lodash": ^4.14.173
|
||||
consola: ^2.15.3
|
||||
create-require: ^1.1.1
|
||||
defu: ^5.0.0
|
||||
@ -1493,6 +1494,7 @@ __metadata:
|
||||
hash-sum: ^2.0.0
|
||||
hookable: ^5.0.0
|
||||
jiti: ^1.12.3
|
||||
lodash: ^4.17.21
|
||||
pathe: ^0.2.0
|
||||
rc9: ^1.2.0
|
||||
scule: ^0.2.1
|
||||
@ -10087,7 +10089,6 @@ fsevents@~2.3.2:
|
||||
"@nuxt/webpack-builder": ^0.10.0
|
||||
"@types/fs-extra": ^9.0.13
|
||||
"@types/hash-sum": ^1.0.0
|
||||
"@types/lodash": ^4.14.173
|
||||
"@vue/reactivity": 3.2.16
|
||||
"@vue/server-renderer": ^3.2.16
|
||||
"@vue/shared": 3.2.16
|
||||
@ -10100,7 +10101,6 @@ fsevents@~2.3.2:
|
||||
hash-sum: ^2.0.0
|
||||
hookable: ^5.0.0
|
||||
ignore: ^5.1.8
|
||||
lodash: ^4.17.21
|
||||
nuxi: ^0.10.0
|
||||
ohmyfetch: ^0.3.1
|
||||
pathe: ^0.2.0
|
||||
|
Loading…
Reference in New Issue
Block a user