Directus URLs For SSR And Client-Side In Docker

by Alex Johnson 48 views

Hey there! If you're using Directus with Nuxt 3 in a Dockerized environment, you might have bumped into a tricky situation when it comes to managing URLs for server-side rendering (SSR) and client-side requests. Let's dive into the details, explore the challenge, and consider a solution that could make your life a whole lot easier. I'll explain how to properly configure your Nuxt project when using Directus in Docker.

The Core Challenge: URL Configuration

At the heart of the matter lies the need to distinguish between how your server-side (SSR) and client-side components interact with your Directus instance. Specifically, when you're running your application inside Docker containers, the way you access Directus changes depending on the context of the request. Let me elaborate on the core issue and explore the environment setup in more detail.

Understanding the Dockerized Setup

Imagine you have a setup where Directus is humming along in its own Docker container, let's call it cms_directus. Your Nuxt 3 application is also happily residing in its own container, all cozy within the same Docker network. To spice things up, you’ve also exposed Directus to the outside world using a public domain, like https://cms.example.com. This setup is typical for production deployments, but it's the source of the problem. Local development is often straightforward, often using http://localhost:8055. However, things get interesting when you deploy everything to production with Docker.

The SSR Conundrum: Internal vs. Public

When your Nuxt 3 application performs server-side rendering (SSR), it needs to fetch data from Directus. Inside the Docker container where your Nuxt app is running, localhost points to itself, not to the Directus container. The SSR process, therefore, can't reliably use localhost to reach your Directus instance. Instead, it must use the internal Docker hostname, such as http://cms_directus:8055. This distinction is crucial for SSR requests. However, client-side requests, such as those originating from your user's browser, must use the public domain (https://cms.example.com).

Current Limitations and Pain Points

Right now, the nuxt-directus-sdk (or similar SDKs) often require a single Directus URL configuration. This limitation creates a headache in Docker environments. When you configure a single URL, you run into problems. If you set the internal Docker hostname (http://cms_directus:8055), your client-side requests will fail, leading to CORS issues and other network problems. If you use the public domain (https://cms.example.com), your SSR requests inside the Docker container won't work, because the server won't be able to resolve it.

The Proposed Solution: Separate URLs for SSR and Client-Side

To solve these problems, a feature that supports two separate URLs for Directus would be ideal.

Two URL Configurations

The proposed solution involves configuring:

  1. internalUrl: This URL is specifically for server-side (SSR) requests. It should point to the internal Docker hostname, such as http://cms_directus:8055.
  2. publicUrl: This URL is for client-side (browser) requests. It should point to your public domain, such as https://cms.example.com.

Benefits of this Approach

By implementing this, you can:

  • Ensure that your Nuxt SSR can reliably fetch data inside Docker using the internal network.
  • Seamlessly serve browser requests to your public Directus API.
  • Eliminate CORS and other network issues that arise from URL mismatches.

Implementation Considerations and Best Practices

Let's consider the ways to implement this and some important best practices.

Modifying the SDK (if necessary)

If the nuxt-directus-sdk or the SDK you're using doesn’t support separate URLs, it might be necessary to modify it. You would need to add configuration options for internalUrl and publicUrl. Within the SDK, you could then use internalUrl for SSR requests and publicUrl for client-side requests. The SDK will handle the complexity of determining which URL to use based on the context of the request (SSR or client-side).

Environment Variables

Use environment variables to configure the URLs. For instance, in your docker-compose.yml or your deployment setup, you'd define the DIRECTUS_INTERNAL_URL and DIRECTUS_PUBLIC_URL variables. Your Nuxt application then reads these variables to configure the Directus SDK.

// Example in your Nuxt configuration file (nuxt.config.ts)
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      directusPublicUrl: process.env.DIRECTUS_PUBLIC_URL,
    },
    private: {
      directusInternalUrl: process.env.DIRECTUS_INTERNAL_URL,
    },
  },
  // Use in your plugins or composables
  plugins: [
    () => {
      const { public, private } = useRuntimeConfig()
      const directusInternalUrl = private.directusInternalUrl
      const directusPublicUrl = public.directusPublicUrl
      // Initialize your Directus SDK using the appropriate URL
    },
  ],
})

Server-Side and Client-Side Logic

When fetching data in your Nuxt app, you'll need to determine whether you're on the server or the client. For SSR requests, you'd use the directusInternalUrl. For client-side requests, use the directusPublicUrl. Nuxt provides ways to detect the environment (server or client). With the correct setup, this becomes a breeze.

Testing

Thoroughly test the solution in various environments:

  • Local Development: Verify that both SSR and client-side requests work as expected using the local setup (e.g., localhost).
  • Docker Development: Simulate your production environment by running your Nuxt app and Directus within Docker containers. This will help you identify any issues related to network configuration.
  • Staging/Production: Before deploying to production, deploy to a staging environment and conduct extensive testing. This will allow you to catch and fix any issues before they affect your users.

Conclusion: Improving Directus Integration in Dockerized Nuxt 3 Projects

Supporting separate internal and public Directus URLs for SSR and client-side requests is a critical enhancement when using Directus with Nuxt 3 in a Docker environment. This approach eliminates CORS and network issues, providing a seamless and reliable experience for both server-side rendering and client-side interactions. While it may require modifying or extending the capabilities of the SDK, the benefits—improved performance, reliability, and ease of deployment—make it a worthwhile consideration.

By implementing the ideas discussed here, you can streamline the development and deployment processes and build a more robust and scalable web application. Remember to test thoroughly in various environments to make sure everything works perfectly. Feel free to seek assistance from the community or the project maintainers if you encounter any difficulties.

For additional support and assistance on how to build your project, check out Directus documentation

Happy coding!