Skip to content

ipx runtime config documentation is misleading, not actually possible to provide list of domains at runtime #2088

@IlyaSemenov

Description

@IlyaSemenov

#1738 added this documentation:

You can update the options for `ipx` at runtime by passing the appropriate environment variable. For example:
```ts [nuxt.config.ts]
export default defineNuxtConfig({
runtimeConfig: {
ipx: {
baseURL: process.env.NUXT_IPX_BASE_URL || '/_ipx',
alias: {
someAlias: process.env.NUXT_IPX_ALIAS_SOME_ALIAS || ''
},
http: {
domains: process.env.NUXT_IPX_HTTP_DOMAINS,
},

The example says "You can update the options at runtime by passing the appropriate environment variable." and then it shows the actual usage of environment variables, but this is build-time usage, not run-time.

This code is a misleading antipattern. It misleads a user that they can refer to process.env in nuxt.config.ts and this will effective in runtime, which is not so. Whatever references to process.env are there in defineNuxtConfig, they are resolved during build time, and then literally imprinted to the output code:

image/src/module.ts

Lines 159 to 165 in 5d983d8

// Add runtime options
addTemplate({
filename: 'image-options.mjs',
getContents() {
return generateImageOptions(providers, imageOptions)
},
})

While NUXT_IPX_HTTP_DOMAINS indeed has runtime effect on the server ipx configuration, it is not happening because of reference to process.env.NUXT_IPX_HTTP_DOMAINS in the code above. It is caused by useRuntimeConfig().ipx inside routes/_ipx.ts.


Then, contrary to what the documentation implies, it is not possible to provide the list of domains at runtime with an environment variable.

The list of domains in resolveImage is taken from ctx.options:

// Externalize remote images if domain does not match with `domains`
if (provider.validateDomains && hasProtocol(input)) {
const inputHost = parseURL(input).host
// Domains are normalized to hostname in module
if (!ctx.options.domains.find(d => d === inputHost)) {
return {
url: input,
}
}
}

which is directly passed from image-options.mjs which is generated at build time and does not use the runtime config:

import { imageOptions } from '#build/image-options.mjs'
import { useNuxtApp, useRuntimeConfig } from '#imports'
export const useImage = (event?: H3Event): $Img => {
const config = useRuntimeConfig()
const nuxtApp = useNuxtApp()
return nuxtApp.$img as $Img || nuxtApp._img || (nuxtApp._img = createImage({
...imageOptions,

Luckily, the options object is exposed by useImage() and one can fiddle with it in a plugin:

export default defineNuxtPlugin(async () => {
  // Make `<nuxt-img>` use runtime list of domains.
  // This relies on the respective server plugin that injects the data into Nuxt payload.
  useImage().options.domains = useNuxtApp().payload.imageDomains
})

What I propose is:

  1. At the very least, update the documentation and remove misleading use of process.env in defineNuxtConfig():
- domains: process.env.NUXT_IPX_HTTP_DOMAINS,
+ domains: [], // Set in run-time with NUXT_IPX_HTTP_DOMAINS
  1. Actually add a way to provide runtime environment variables (make them public and thus accessible client-side).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions