feat(nuxt): prompt to autoinstall @nuxt/image when it is used (#23717)

This commit is contained in:
Daniel Roe 2023-10-17 12:07:31 +01:00 committed by GitHub
parent e64ece70c0
commit 6141c08a44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 9 deletions

View File

@ -0,0 +1,17 @@
import { createError } from '../composables/error'
function renderStubMessage (name: string) {
throw createError({
fatal: true,
statusCode: 500,
statusMessage: `${name} is provided by @nuxt/image. Check your console to install it or run 'npx nuxi@latest module add @nuxt/image'`
})
}
export const NuxtImg = {
setup: () => renderStubMessage('<NuxtImg>')
}
export const NuxtPicture = {
setup: () => renderStubMessage('<NuxtPicture>')
}

View File

@ -46,6 +46,11 @@ export const loaderPlugin = createUnplugin((options: LoaderOptions) => {
s.replace(/(?<=[ (])_?resolveComponent\(\s*["'](lazy-|Lazy)?([^'"]*?)["'][\s,]*[^)]*\)/g, (full: string, lazy: string, name: string) => {
const component = findComponent(components, name, options.mode)
if (component) {
// @ts-expect-error TODO: refactor to nuxi
if (component._internal_install) {
// @ts-expect-error TODO: refactor to nuxi
import('../core/features').then(({ installNuxtModule }) => installNuxtModule(component._internal_install))
}
let identifier = map.get(component) || `__nuxt_component_${num++}`
map.set(component, identifier)

View File

@ -1,6 +1,6 @@
import { addDependency } from 'nypm'
import { resolvePackageJSON } from 'pkg-types'
import { logger } from '@nuxt/kit'
import { logger, useNuxt } from '@nuxt/kit'
import { isCI, provider } from 'std-env'
const isStackblitz = provider === 'stackblitz'
@ -11,10 +11,7 @@ export interface EnsurePackageInstalledOptions {
prompt?: boolean
}
export async function ensurePackageInstalled (
name: string,
options: EnsurePackageInstalledOptions
) {
async function promptToInstall (name: string, installCommand: () => Promise<void>, options: EnsurePackageInstalledOptions) {
if (await resolvePackageJSON(name, { url: options.searchPaths }).catch(() => null)) {
return true
}
@ -39,10 +36,7 @@ export async function ensurePackageInstalled (
logger.info(`Installing ${name}...`)
try {
await addDependency(name, {
cwd: options.rootDir,
dev: true
})
await installCommand()
logger.success(`Installed ${name}`)
return true
} catch (err) {
@ -50,3 +44,22 @@ export async function ensurePackageInstalled (
return false
}
}
// TODO: refactor to Nuxi
const installPrompts = new Set<string>()
export function installNuxtModule (name: string, options?: EnsurePackageInstalledOptions) {
if (installPrompts.has(name)) { return }
installPrompts.add(name)
const nuxt = useNuxt()
return promptToInstall(name, async () => {
const { runCommand } = await import('nuxi')
await runCommand('module', ['add', name, '--cwd', nuxt.options.rootDir])
}, { rootDir: nuxt.options.rootDir, searchPaths: nuxt.options.modulesDir, ...options })
}
export function ensurePackageInstalled (name: string, options: EnsurePackageInstalledOptions) {
return promptToInstall(name, () => addDependency(name, {
cwd: options.rootDir,
dev: true
}), options)
}

View File

@ -305,6 +305,18 @@ async function initNuxt (nuxt: Nuxt) {
}
}
// Add stubs for <NuxtImg> and <NuxtPicture>
for (const name of ['NuxtImg', 'NuxtPicture']) {
addComponent({
name,
export: name,
priority: -1,
filePath: resolve(nuxt.options.appDir, 'components/nuxt-stubs'),
// @ts-expect-error TODO: refactor to nuxi
_internal_install: '@nuxt/image'
})
}
// Add prerender payload support
if (!nuxt.options.dev && nuxt.options.experimental.payloadExtraction) {
addPlugin(resolve(nuxt.options.appDir, 'plugins/payload.client'))