nuxt / image

Plug-and-play image optimization for Nuxt applications.
https://image.nuxt.com
MIT License
1.34k stars 270 forks source link

Request for Enhancing Nuxt Image Module with Environment Variable Support #1427

Open Vahagn-Zaqaryan opened 2 months ago

Vahagn-Zaqaryan commented 2 months ago

Hi everyone,

First, I want to thank the team for all the hard work on this Nuxt module. The real-time optimizations and quick loading times are truly impressive and have made working with Nuxt a great experience.

I'm currently developing a website builder with Nuxt and Directus CMS, and everything has been smooth so far. As I prepare to deploy and scale, it's crucial for me to build the app once and use the same build across different environments. I explored the Nuxt Runtime Config and tried to configure the Nuxt Image module using environment variables. My initial setup was:

image: {
  domains: ['cms.example.com'],

  alias: {
    cms: 'https://cms.example.com/assets/',
  },

  providers: {
    directus: {
      provider: 'directus',
      options: {
        baseURL: 'https://directus.example.com/assets/',
      },
    },
  },
}

I converted this into environment variables:

# Nuxt Image
NUXT_IMAGE_DOMAINS="cms.example.com"
NUXT_IMAGE_ALIAS_CMS="https://cms.example.com/assets/"
NUXT_IMAGE_PROVIDERS_DIRECTUS_PROVIDER="directus"
NUXT_IMAGE_PROVIDERS_DIRECTUS_OPTIONS_BASE_URL="https://directus.example.com"

However, I discovered that only NUXT_IMAGE_DOMAINS and NUXT_IMAGE_PROVIDER are supported as environment variables, according to the documentation and source code.

It would be highly beneficial if the module could support more configuration through environment variables, similar to other modules like i18n. This enhancement would make the module even more powerful for projects requiring deployment across multiple environments.

I understand that this may take time to implement. In the meantime, if anyone has a workaround or suggestions, I would greatly appreciate your advice.

Thank you again, I look forward to your feedback and any guidance you can provide ⚡️

Vahagn-Zaqaryan commented 2 months ago

I took some time to reflect and did additional research on this issue. It seems the solution could be straightforward. I reviewed the implementation of the nuxt-gtag module, and here’s what I found:

nuxt.options.runtimeConfig.public.gtag = defu(
  nuxt.options.runtimeConfig.public.gtag,
  options,
)

In this example, the options provided by the runtime config are merged with those specified in the nuxt.config.ts file. Later in the module, these options are accessed as follows:

const options = useRuntimeConfig().public.gtag as Required<ModuleOptions>

This approach is ideal as it allows the entire module to be fully dependent on environment variable configurations.

On further reflection, I believe there might be a broader issue with how environment variable injection is currently implemented. The existing method places the responsibility on module creators to use the runtime config internally and expose the options. However, a better approach might be to separate concerns and allow modules to be configured entirely at runtime, perhaps like this:

export default defineNuxtConfig({
  // ... other configs ...
  hooks: {
    'config:extend': (nuxtApp) => {
      const config = useRuntimeConfig()
      nuxtApp.config.globalProperties.image = {
        domains: [config.public.domain],
        // ... other image configurations ...
      }
    }
  }
})

Alternatively, it could be beneficial to have a mechanism that wraps the module inside another module, enabling the use of runtime config seamlessly.

cjpearson commented 2 months ago

1247 might be a helpful prerequisite for this topic. It allows image providers to access the runtime config. Additional work would still need to be done for providers to use the runtime config.

Vahagn-Zaqaryan commented 1 month ago

Thanks so much, @cjpearson, for the solution! Apologies for the delayed reply, I’ve been busy releasing this website builder 🎉

I avoided patching the package since it didn’t feel right (my reasoning is that it adds another dependency to manage). Instead, I used AWS Amplify and CloudFormation to get the job done!

Although this worked out quite well, I still find the way the runtimeConfig is handled a bit strange.