Part 90: Making Image Optimization Configurable in Next.js with Environment Variables

[App] Deploying with External Services

[App] Deploying with External Services

In our journey to create a flexible and adaptable Next.js application, we've taken significant steps to ensure that our configuration is environment-agnostic. One such aspect is the CMS_URL, which we successfully made configurable using environment variables. This time, we'll delve into another critical component that requires similar flexibility: Image Optimization.

The Challenge: Configuring Image Sources

Next.js provides a powerful Image Optimization feature that requires configuration of remote patterns, especially when images are served from an external CMS like Strapi. This configuration involves specifying parts of the CMS URL such as protocol, hostname, and port. The challenge arises when the CMS_URL changes, as we need to ensure that the image configuration also reflects this change.

Leveraging Environment Variables for Image Configuration

Step 1: Understanding the Remote Pattern

A remote pattern in Next.js Image Optimization is an object containing separate properties for protocol, hostname, and port. These properties should match the CMS URL used by your application.

Step 2: Reading Environment Variables in next.config.js

The next.config.js file, despite its name, is a JavaScript file. This means you can use JavaScript code, including reading environment variables. Let's log the CMS_URL to confirm:

console.log('CMS_URL in config:', process.env.CMS_URL);

This confirms that we can access environment variables here just like any other JavaScript file.

Step 3: Creating a URL Object

To dynamically create the remote pattern object, we can leverage the URL API. By parsing the CMS_URL, we obtain an object with all necessary properties.

const url = new URL(process.env.CMS_URL);

This object provides separate properties for hostname, port, and protocol, which align perfectly with the remote pattern requirements.

Step 4: Configuring the Remote Pattern

With the URL object, we can set up the remote pattern dynamically:

{
  protocol: url.protocol.replace(':', ''), // Removing the colon
  hostname: url.hostname,
  port: url.port,
  pathname: '/uploads/**', // Specific to Strapi image paths
}

The pathname is specific to the image paths served by your CMS. In this case, Strapi serves images under /uploads/**.

Step 5: Using a Separate Environment Variable for Image Paths

To avoid hardcoding paths, define a separate environment variable, CMS_IMAGE_PATTERN, which includes the path for image uploads:

CMS_IMAGE_PATTERN="http://localhost:1337/uploads/**"

This allows us to maintain different URL values for API calls and image loading.

Step 6: Creating a Helper Function

To keep the configuration clean, create a helper function to convert a URL string into a remote pattern object:

function toRemotePattern(urlString) {
  const url = new URL(urlString);
  return {
    protocol: url.protocol.replace(':', ''),
    hostname: url.hostname,
    port: url.port,
    pathname: url.pathname,
  };
}

Use this function in the next.config.js file:

module.exports = {
  images: {
    remotePatterns: [
      toRemotePattern(process.env.CMS_IMAGE_PATTERN),
    ],
  },
};

This approach allows you to easily add more remote patterns if necessary.

Final Touches and Testing

After implementing these changes, test the configuration by changing the CMS_URL and CMS_IMAGE_PATTERN to different values, such as switching between localhost and 127.0.0.1. Remember to restart the server when modifying next.config.js to ensure changes are applied.

Conclusion

By making the image source configurable through environment variables, you gain flexibility and reduce hardcoding within your Next.js application. This approach ensures that as your application scales and environments change, the configuration remains robust and adaptable. With these steps, you can seamlessly handle image optimization in a dynamic, environment-specific manner.

Last updated