vercel / next.js

The React Framework
https://nextjs.org
MIT License
123.07k stars 26.3k forks source link

BUG: Can't load node-addon like @napi-rs/image in appDir api route #59648

Open promer94 opened 6 months ago

promer94 commented 6 months ago

Link to the code that reproduces this issue

https://github.com/promer94/napi-rs-image-nextjs14-bug

To Reproduce

  1. clone and run the repo
  2. upload a image to /image will see the error in console

Current vs. Expected behavior

Currently the rust node addon could not be loaded correctly when using route.ts in App Router.

CleanShot 2023-12-15 at 16 53 27@2x

Verify canary release

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.2.0: Wed Nov 15 21:53:18 PST 2023; root:xnu-10002.61.3~2/RELEASE_ARM64_T6000
Binaries:
  Node: 20.9.0
  npm: 10.1.0
  Yarn: N/A
  pnpm: 8.9.0
Relevant Packages:
  next: 14.0.4
  eslint-config-next: 14.0.4
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.3.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

App Router

Additional context

No response

Yovach commented 6 months ago

Hi @promer94, I'm using @node-rs/argon2 and I previously had the same issue. I fixed by adding the package in experimental.serverComponentsExternalPackages like :

// next.config.js
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@node-rs/argon2"],
  },
};

In your case, it'll be :

// next.config.js

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@napi-rs/image"],
  },
};
module.exports = nextConfig;
elitan commented 6 months ago
// next.config.js

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@napi-rs/image"],
  },
};
module.exports = nextConfig;

worked perfectly for me. Thank you. This issue can be closed.

pulgueta commented 2 months ago

Hi @promer94, I'm using @node-rs/argon2 and I previously had the same issue. I fixed by adding the package in experimental.serverComponentsExternalPackages like :

// next.config.js
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@node-rs/argon2"],
  },
};

In your case, it'll be :

// next.config.js

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@napi-rs/image"],
  },
};
module.exports = nextConfig;

Hey @Yovach, I'm trying to use @node-rs/argon2 package but doesn't work although I set the package under the experimental feature in the Next.js config file, neither argon2, bcrypt seem to work even if I set the packages there. Any suggestions?

Yovach commented 2 months ago

Hi @promer94, I'm using @node-rs/argon2 and I previously had the same issue. I fixed by adding the package in experimental.serverComponentsExternalPackages like :

// next.config.js
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@node-rs/argon2"],
  },
};

In your case, it'll be :

// next.config.js

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@napi-rs/image"],
  },
};
module.exports = nextConfig;

Hey @Yovach, I'm trying to use @node-rs/argon2 package but doesn't work although I set the package under the experimental feature in the Next.js config file, neither argon2, bcrypt seem to work even if I set the packages there. Any suggestions?

Hi @pulgueta, can you provide your next.config.js ? Are you using Turbopack ? Which version of Next.js ?

pulgueta commented 2 months ago

Hi @promer94, I'm using @node-rs/argon2 and I previously had the same issue. I fixed by adding the package in experimental.serverComponentsExternalPackages like :

// next.config.js
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@node-rs/argon2"],
  },
};

In your case, it'll be :

// next.config.js

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@napi-rs/image"],
  },
};
module.exports = nextConfig;

Hey @Yovach, I'm trying to use @node-rs/argon2 package but doesn't work although I set the package under the experimental feature in the Next.js config file, neither argon2, bcrypt seem to work even if I set the packages there. Any suggestions?

Hi @pulgueta, can you provide your next.config.js ? Are you using Turbopack ? Which version of Next.js ?

Hey there! Here is my config file:

// next.config.mjs
import { fileURLToPath } from 'node:url';

import createJITI from 'jiti';

const jiti = createJITI(fileURLToPath(import.meta.url));

jiti('./env.server.ts');

/** @type {import('next').NextConfig} */
const nextConfig = {
    poweredByHeader: false,
    reactStrictMode: true,
    logging: {
        fetches: {
            fullUrl: true,
        },
    },
    experimental: {
        staleTimes: {
            dynamic: 0,
        },
        serverComponentsExternalPackages: ['argon2']
    },
    webpack: (config, { isServer, webpack }) => {
        config.plugins.push(
            new webpack.NormalModuleReplacementPlugin(/^node:/, (resource) => {
                resource.request = resource.request.replace(/^node:/, '');
            }),
        );

        if (!isServer) {
            config.resolve.fallback = {
                fs: false,
            };
        }

        config.module.rules.push({
            test: /\.wasm$/,
            loader: 'base64-loader',
            type: 'javascript/auto',
        });

        config.module.noParse = /\.wasm$/;

        config.module.rules.forEach((rule) => {
            (rule.oneOf || []).forEach((oneOf) => {
                if (oneOf.loader && oneOf.loader.indexOf('file-loader') >= 0) {
                    oneOf.exclude.push(/\.wasm$/);
                }
            });
        });

        if (!isServer) {
            config.resolve.fallback.fs = false;
        }

        config.plugins.push(
            new webpack.IgnorePlugin({ resourceRegExp: /\/__tests__\// }),
        );

        return config;
    },
};

export default nextConfig;

I'm not using Turbopack and my current version of Next.js is 14.2.3. Doesn't work for argon2, bcrypt, @node-rs/bcrypt nor @node-rs/argon2. Had to switch to bcryptjs which is super slow.

Yovach commented 2 months ago

Hi @promer94, I'm using @node-rs/argon2 and I previously had the same issue. I fixed by adding the package in experimental.serverComponentsExternalPackages like :

// next.config.js
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@node-rs/argon2"],
  },
};

In your case, it'll be :

// next.config.js

/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["@napi-rs/image"],
  },
};
module.exports = nextConfig;

Hey @Yovach, I'm trying to use @node-rs/argon2 package but doesn't work although I set the package under the experimental feature in the Next.js config file, neither argon2, bcrypt seem to work even if I set the packages there. Any suggestions?

Hi @pulgueta, can you provide your next.config.js ? Are you using Turbopack ? Which version of Next.js ?

Hey there! Here is my config file:

// next.config.mjs
import { fileURLToPath } from 'node:url';

import createJITI from 'jiti';

const jiti = createJITI(fileURLToPath(import.meta.url));

jiti('./env.server.ts');

/** @type {import('next').NextConfig} */
const nextConfig = {
  poweredByHeader: false,
  reactStrictMode: true,
  logging: {
      fetches: {
          fullUrl: true,
      },
  },
  experimental: {
      staleTimes: {
          dynamic: 0,
      },
      serverComponentsExternalPackages: ['argon2']
  },
  webpack: (config, { isServer, webpack }) => {
      config.plugins.push(
          new webpack.NormalModuleReplacementPlugin(/^node:/, (resource) => {
              resource.request = resource.request.replace(/^node:/, '');
          }),
      );

      if (!isServer) {
          config.resolve.fallback = {
              fs: false,
          };
      }

      config.module.rules.push({
          test: /\.wasm$/,
          loader: 'base64-loader',
          type: 'javascript/auto',
      });

      config.module.noParse = /\.wasm$/;

      config.module.rules.forEach((rule) => {
          (rule.oneOf || []).forEach((oneOf) => {
              if (oneOf.loader && oneOf.loader.indexOf('file-loader') >= 0) {
                  oneOf.exclude.push(/\.wasm$/);
              }
          });
      });

      if (!isServer) {
          config.resolve.fallback.fs = false;
      }

      config.plugins.push(
          new webpack.IgnorePlugin({ resourceRegExp: /\/__tests__\// }),
      );

      return config;
  },
};

export default nextConfig;

I'm not using Turbopack and my current version of Next.js is 14.2.3. Doesn't work for argon2, bcrypt, @node-rs/bcrypt nor @node-rs/argon2. Had to switch to bcryptjs which is super slow.

Is there an error?

snspinn commented 1 month ago

Still seeing this intermittently even after setting serverComponentsExternalPackages. The full next.config.mjs is very basic:

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    serverComponentsExternalPackages: ["my-package"],
  },
};

export default nextConfig;

Seems like deleting node_modules/, .next/, .yarn and yarn.lock followed by a fresh yarn install does the trick. I am finding this with both production and dev builds (in dev builds it pops up only when I trying to use the function, of course). Wish I could be more specific as to what is the root cause but it's fairly inconsistent. I'm using moon monorepo so perhaps I should remove caching on of builds.

Anyway, the error is:

../../../libraries/my-package/my-package.linux-x64-gnu.node
Module parse failed: Unexpected character '' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
Import trace for requested module:
../../../libraries/my-package/my-package.linux-x64-gnu.node
../../../libraries/my-package/index.js
./src/app/api/files/upload/route.ts
> Build failed because of webpack errors

next version: 14.2.1