50 lines
2.2 KiB
Markdown
50 lines
2.2 KiB
Markdown
|
---
|
||
|
title: "Next.js error about native node modules using bindings"
|
||
|
date: 2023-08-13T16:44:41Z
|
||
|
toc: false
|
||
|
images:
|
||
|
tags:
|
||
|
- dev
|
||
|
---
|
||
|
|
||
|
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](https://www.npmjs.com/package/libheif-node-dy) that uses [bindings](https://www.npmjs.com/package/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](https://github.com/TooTallNate/node-bindings/issues/61) 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:
|
||
|
|
||
|
```js
|
||
|
/** @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.
|