diff --git a/src/module.ts b/src/module.ts index 1d251cb85..e76c0162a 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1,10 +1,10 @@ import process from 'node:process' import { parseURL, withLeadingSlash } from 'ufo' -import { defineNuxtModule, addTemplate, addImports, createResolver, addComponent, addPlugin } from '@nuxt/kit' +import { defineNuxtModule, addTemplate, addImports, addServerImports, createResolver, addComponent, addPlugin } from '@nuxt/kit' import { resolve } from 'pathe' import { resolveProviders, detectProvider, resolveProvider } from './provider' -import type { ImageProviders, ImageOptions, InputProvider, CreateImageOptions } from './types' +import type { ImageProviders, ImageOptions, InputProvider, CreateImageOptions, ImageModuleProvider } from './types' export interface ModuleOptions extends ImageProviders { inject: boolean @@ -121,18 +121,17 @@ export default defineNuxtModule({ addTemplate({ filename: 'image-options.mjs', getContents() { - return ` -${providers.map(p => `import * as ${p.importName} from '${p.runtime}'`).join('\n')} - -export const imageOptions = ${JSON.stringify(imageOptions, null, 2)} - -imageOptions.providers = { -${providers.map(p => ` ['${p.name}']: { provider: ${p.importName}, defaults: ${JSON.stringify(p.runtimeOptions)} }`).join(',\n')} -} - ` + return generateImageOptions(providers, imageOptions) }, }) + addServerImports([ + { + name: 'useImage', + from: resolver.resolve('runtime/server/utils/image'), + }, + ]) + nuxt.hook('nitro:init', async (nitro) => { if (!options.provider || options.provider === 'ipx' || options.provider === 'ipxStatic' || options.ipx) { const resolvedProvider = nitro.options.static || options.provider === 'ipxStatic' @@ -162,6 +161,8 @@ ${providers.map(p => ` ['${p.name}']: { provider: ${p.importName}, defaults: ${ await p.setup(p, options, nuxt) } } + // runtime options to use in nitro environment + nitro.options.virtual['#image-options'] = generateImageOptions(providers, imageOptions) }) if (options.inject) { @@ -180,3 +181,15 @@ function pick, K extends keyof O>(obj: O, keys: K[]): } return newobj } + +function generateImageOptions(providers: ImageModuleProvider[], imageOptions: Omit): string { + return ` + ${providers.map(p => `import * as ${p.importName} from '${p.runtime}'`).join('\n')} + + export const imageOptions = ${JSON.stringify(imageOptions, null, 2)} + + imageOptions.providers = { + ${providers.map(p => ` ['${p.name}']: { provider: ${p.importName}, defaults: ${JSON.stringify(p.runtimeOptions)} }`).join(',\n')} + } + ` +} diff --git a/src/runtime/image.ts b/src/runtime/image.ts index b7742ba58..3f2492069 100644 --- a/src/runtime/image.ts +++ b/src/runtime/image.ts @@ -5,16 +5,15 @@ import { imageMeta } from './utils/meta' import { checkDensities, parseDensities, parseSize, parseSizes } from './utils' import { prerenderStaticImages } from './utils/prerender' -export function createImage(globalOptions: CreateImageOptions) { +export function createImage(globalOptions: CreateImageOptions, isCalledInNitro: boolean = false) { const ctx: ImageCTX = { options: globalOptions, } const getImage: $Img['getImage'] = (input: string, options = {}) => { const image = resolveImage(ctx, input, options) - // Prerender static images - if (import.meta.server && import.meta.prerender) { + if (import.meta.server && import.meta.prerender && !isCalledInNitro) { prerenderStaticImages(image.url) } diff --git a/src/runtime/server/utils/image.ts b/src/runtime/server/utils/image.ts new file mode 100644 index 000000000..e7a91e1fb --- /dev/null +++ b/src/runtime/server/utils/image.ts @@ -0,0 +1,18 @@ +import type { Img } from '../../../module' + +import { createImage } from '../../image' +// @ts-expect-error virtual file +import { imageOptions } from '#image-options' +import { useRuntimeConfig } from '#imports' + +export const useImage = (): Img => { + const config = useRuntimeConfig() + + return createImage({ + ...imageOptions, + nuxt: { + baseURL: config.app.baseURL, + }, + runtimeConfig: config, + }, true) +}