This might be a little niche, but I had trouble finding anyone else write about it so I might as well.

I was trying to use a native node module libheif-node-dy that uses bindings in a Next.js app, and I kept getting errors from bindings:

- error node_modules/.pnpm/bindings@1.5.0/node_modules/bindings/bindings.js (179:15) @ indexOf
- error Error [TypeError]: Cannot read properties of undefined (reading 'indexOf')
    at Function.getFileName (webpack-internal:///(rsc)/./node_modules/.pnpm/bindings@1.5.0/node_modules/bindings/bindings.js:193:18)
    at bindings (webpack-internal:///(rsc)/./node_modules/.pnpm/bindings@1.5.0/node_modules/bindings/bindings.js:130:52)

After a little digging, I came across this Github issue by Nicholas Ramz who diagnosed the issue down to the Webpack/Terser minimizer, which removes a line that looks like a no-op but is actually supposed to trigger an error stack. Bindings needs that to happen, otherwise you get this error.

The solution he suggested is that you change your Webpack config to disable that Terser optimization. This is sounds like a good solution, but it’s a bit hard to apply to Next.js because I don’t have a webpack config of myself. Next.js has it’s Webpack config built-in, and while it allows you to override it the documentation is a little bare.

I found an easier solution for Next.js though: you can tell Next.js to not bundle a module. You can configure this with the serverComponentsExternalPackages option. My config file now looks like this:

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

module.exports = nextConfig;

And this immediately worked, the module no longer gets bundled but instead executed like a regular node module, which gets around this issue. Since native modules can’t be bundled into a JS file anyway, I don’t think you lose much by disabling bundling just for native modules anyway.