Búsqueda de sitios web

node.js - importar un addon .node con ESM


Estoy intentando importar un complemento binario .node en un contexto basado en ESM y Node con TypeScript. Sin embargo, cuando intento hacer esto, obtengo el siguiente error "error TS2307: No se puede encontrar el módulo './addon.node' o sus declaraciones de tipo correspondientes."

He buscado en línea varias soluciones, estas son mis versiones: NodeJS: v16.14.1 ts-node: v10.7.0 Typescript: 4.6.3

Este es mi enfoque actual para importar:

import addon from "./addon.node";

Solo para señalar, debido a mi configuración estoy limitado a usar únicamente import. Gracias de antemano por cualquier apoyo.

Respuesta #1

Node.js import no admite archivos .node. Para importar dichos archivos en un contexto ESM, necesitas usar createRequire:

import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);

const addon = require('./addon.node');

También podrías importar el archivo .node en un archivo CommonJS que luego importe un archivo ESM.

// addon.cjs
module.exports = require('./addon.node');

// main.js
import addon from './addon.cjs';

Finalmente, podrías crear un cargador ESM que agregue soporte para archivos .node a import, envolviendo el método createRequire en un cargador (sin probar):

import { cwd } from 'node:process';
import { pathToFileURL } from 'node:url';

const baseURL = pathToFileURL(`${cwd()}/`).href;

export async function resolve(specifier, context, nextResolve) {
  if (specifier.endsWith('.node')) {
    const { parentURL = baseURL } = context;

    // Node.js normally errors on unknown file extensions, so return a URL for
    // specifiers ending in `.node`.
    return {
      shortCircuit: true,
      url: new URL(specifier, parentURL).href,
    };
  }

  // Let Node.js handle all other specifiers.
  return nextResolve(specifier);
}

export async function load(url, context, nextLoad) {
  if (url.endsWith('.node')) {
    const source = `
      import { createRequire } from 'node:module';
      import { fileURLToPath } from 'node:url';
      const require = createRequire(import.meta.url);
      const path = fileURLToPath(${url});
      export default require(path);`;

    return {
      format: 'module',
      shortCircuit: true,
      source,
    };
  }

  // Let Node.js handle all other URLs.
  return nextLoad(url);
}

Artículos relacionados