1

Images like png are successfully displayed on app if locally run next build + next start but after deploying it to Azure Web App via server.js and a web.config, images are not loading anymore.

I have my image under public/imgs/logo.png and I reference it like this: <Image src={'/imgs/logo.png'} height={'20px'} width={'180px'} />

I even tried running the server.js directly(node server.js) once everything is built and the image still loads. But once I upload the build files(.next folder), web.config, and server.js in my Azure Web App, the image is not loading anymore.

Please help. Below are some of the files I used to set this up.

server.js

const { createServer } = require("http");
// const express = require('express') (Only if you app uses express)
const next = require("next");

const port = process.env.PORT || 8888;
const isDev = process.env.ENV !== "production";
const app = next({ isDev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  createServer((req, res) => {
    handle(req, res);
  }).listen(port, (err) => {
    if (err) throw err;
    console.log(`Ready on http://localhost:${port}`);
  });
});

web.config

<?xml version="1.0" encoding="utf-8"?>
<!--
     This configuration file is required if iisnode is used to run node processes behind
     IIS or IIS Express.  For more information, visit:

     <https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config>
-->

<configuration>
  <system.webServer>
    <!-- Visit <http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx> for more information on WebSocket support -->
    <webSocket enabled="false" />
    <handlers>
      <!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
      <add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
    </handlers>
    <rewrite>
      <rules>
        <!-- Do not interfere with requests for node-inspector debugging -->
        <rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
          <match url="^server.js\\/debug[\\/]?" />
        </rule>

        <!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
        <rule name="StaticContent">
          <action type="Rewrite" url="public{REQUEST_URI}"/>
        </rule>

        <!-- All other URLs are mapped to the node.js site entry point -->
        <rule name="DynamicContent">
          <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
          </conditions>
          <action type="Rewrite" url="server.js"/>
        </rule>
      </rules>
    </rewrite>

    <!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
    <security>
      <requestFiltering>
        <hiddenSegments>
          <remove segment="bin"/>
        </hiddenSegments>
      </requestFiltering>
    </security>

    <!-- Make sure error responses are left untouched -->
    <httpErrors existingResponse="PassThrough" />

    <!--
      You can control how Node is hosted within IIS using the following options:
        * watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
        * node_env: will be propagated to node as NODE_ENV environment variable
        * debuggingEnabled - controls whether the built-in debugger is enabled

      See <https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config> for a full list of options
    -->
    <iisnode watchedFiles="web.config;*.js"/>
  </system.webServer>
</configuration>

next.config.js

const path = require("path");
require("dotenv").config();
const withImages = require("next-images");

module.exports = withImages({
  reactStrictMode: true,
  eslint: {
    dirs: ["apiclients", "common", "components", "config", "pages", "stores"],
  },
  sassOptions: {
    includePaths: [
      path.join(__dirname, "styles"),
      path.join(__dirname, "components"),
    ],
    prependData: `@import "styles/_variables";`, // prepend _css variables in all css documents
  },
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    config.plugins.push(new webpack.EnvironmentPlugin(process.env));
    return config;
  },
  experiments: {
    asset: true,
  },
});
Arden
  • 51
  • 2
  • 5
  • 3
    You should also copy the "public" directory to Azure. Did you copy? – Moorthy G Aug 31 '21 at 05:14
  • This fixed my problem! :D So basically what I'm doing is that, I'm don't want to deploy my whole source code in Azure Web App Service. I just select which folders to deploy. Namely: node_modules, .next folder, server.js, and web.config. Only thing missing is the public folder. Thank you so much @MoorthyG! :) – Arden Aug 31 '21 at 06:41

1 Answers1

0

The (next/image) component relies on the Next Server running. If you export it in any kind of static configuration being hosted by another service, it fails miserably (unless you do some custom coding to handle the images). I created a php program that redirects images from the /_next/assets/ folder in my circumstances, but what you should also test, is replace one of the <Image tags with an <img tag, and see if that one image displays correctly. If it does, then that's your issue. You could then replace all your tags, but you would loose some advantages such as lazy loading, etc.