Estoy creando un programa para analizar las transmisiones de las cámaras de seguridad y me quedé atascado en la primera línea. Por el momento, mi archivo .js no tiene nada más que la importación de node-fetch y me da un mensaje de error. ¿Qué estoy haciendo mal?
Ejecutando Ubuntu 20.04.2 LTS en el subsistema de Windows para Linux.
Versión de nodo:
user@MYLLYTIN:~/CAMSERVER$ node -v v14.17.6versión del paquete node-fetch:
user@MYLLYTIN:~/CAMSERVER$ npm v node-fetch node-fetch@3.0.0 | MIT | deps: 2 | versions: 63 A light-weight module that brings Fetch API to node.js https://github.com/node-fetch/node-fetch keywords: fetch, http, promise, request, curl, wget, xhr, whatwg dist .tarball: https://registry.npmjs.org/node-fetch/-/node-fetch-3.0.0.tgz .shasum: 79da7146a520036f2c5f644e4a26095f17e411ea .integrity: sha512-bKMI+C7/T/SPU1lKnbQbwxptpCrG9ashG+VkytmXCPZyuM9jB6VU+hY0oi4lC8LxTtAeWdckNCTa3nrGsAdA3Q== .unpackedSize: 75.9 kB dependencies: data-uri-to-buffer: ^3.0.1 fetch-blob: ^3.1.2 maintainers: - endless <jimmy@warting.se> - bitinn <bitinn@gmail.com> - timothygu <timothygu99@gmail.com> - akepinski <npm@kepinski.ch> dist-tags: latest: 3.0.0 next: 3.0.0-beta.10 published 3 days ago by endless <jimmy@warting.se>versión del paquete esm:
user@MYLLYTIN:~/CAMSERVER$ npm v esm esm@3.2.25 | MIT | deps: none | versions: 140 Tomorrow's ECMAScript modules today! https://github.com/standard-things/esm#readme keywords: commonjs, ecmascript, export, import, modules, node, require dist .tarball: https://registry.npmjs.org/esm/-/esm-3.2.25.tgz .shasum: 342c18c29d56157688ba5ce31f8431fbb795cc10 .integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== .unpackedSize: 308.6 kB maintainers: - jdalton <john.david.dalton@gmail.com> dist-tags: latest: 3.2.25 published over a year ago by jdalton <john.david.dalton@gmail.com>Contenido del archivo .js (literalmente nada más que la importación):
user@MYLLYTIN:~/CAMSERVER$ cat server.js import fetch from "node-fetch";Resultado:
user@MYLLYTIN:~/CAMSERVER$ node -r esm server.js /home/user/CAMSERVER/node_modules/node-fetch/src/index.js:1 Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /home/user/CAMSERVER/node_modules/node-fetch/src/index.js require() of ES modules is not supported. require() of /home/user/CAMSERVER/node_modules/node-fetch/src/index.js from /home/user/CAMSERVER/server.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules. Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /home/user/CAMSERVER/node_modules/node-fetch/package.json. at Object.Module._extensions..js (internal/modules/cjs/loader.js:1089:13) { code: 'ERR_REQUIRE_ESM' } user@MYLLYTIN:~/CAMSERVER$Hay un par de maneras de hacer esto:
"type":"module" en package.json--input-type=module cuando ejecute el archivo.mjsnode-fetch v3 es solo para ESM: https://github.com/node-fetch/node-fetch#loading-and-configuring-the-module . El módulo esm que está agregando es para agregar compatibilidad con ESM, pero no es necesario ahora que Node 12+ es compatible con ESM de forma nativa; y no funciona con paquetes solo de ESM como node-fetch 3+.
Para solucionar su problema:
esm ."type": "module" a su package.json . Y eso es. Luego, cuando ejecute node server.js , debería funcionar.
De la Guía de actualización
node-fetch se convirtió para ser un paquete exclusivo de ESM en la versión 3.0.0-beta.10 . node-fetch es un módulo exclusivo de ESM: no puede importarlo con require.
Alternativamente, puede usar la función de importación asincrónica () de CommonJS para cargar la búsqueda de nodos de forma asíncrona:
// mod.cjs const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));o te quedas en v2 como dicen en el README
node-fetches un módulo exclusivo de ESM: no puede importarlo con require. Le recomendamos que permanezca en v2, que está construido con CommonJS, a menos que use ESM usted mismo. Continuaremos publicando correcciones de errores críticos para él.
EDITAR
Lo vi en el documento, lo usé y el script falla con:
error TS2556: un argumento extendido debe tener un tipo de tupla o pasarse a un parámetro de descanso.
Como estás usando mecanografiado, deberías hacer algo como esto
import { RequestInfo, RequestInit } from "node-fetch"; const fetch = (url: RequestInfo, init?: RequestInit) => import("node-fetch").then(({ default: fetch }) => fetch(url, init));Dado que la pregunta se trataba realmente de requerir la búsqueda de nodos y definitivamente hay razones por las que un desarrollador podría necesitar usar require vs import, la respuesta para importar el módulo usando import() es algo precisa pero no está completa, porque ignora el hecho que el uso de la importación es asincrónico y si está usando la búsqueda de nodos en su código en varios lugares, tendrá un poco de lío asincrónico por todas partes cada vez que quiera usar la búsqueda de nodos, por lo que la respuesta es muy en mi humilde opinión incompleto. Una respuesta más completa incluiría un mejor procedimiento. Algo como lo siguiente:
Debe usar import() en lugar de require porque este es un módulo ES. Para evitar un problema asíncrono, querrá esperar la importación de este módulo una vez y luego poder usarlo donde lo necesite. Para hacer eso, cree un módulo que importe cualquiera de sus módulos exclusivos de ES algo como esto:
"use strict"; let got; let fetch; module.exports.load = async function() { queueMicrotask(function() { // any ESM-only module that needs to be loaded can be loaded here, just add import for each using specific structure of each import("got").then(({default: Got}) => got = Got ); fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args)); }); while( // check each module to see if it's been loaded here !got || !got.get || !fetch || typeof fetch !== "function" ) { // waiting for modules to load console.log("Waiting for ES-Only modules to load..."); await new Promise((resolve)=>setTimeout(resolve, 1000)); } module.exports.got = got; module.exports.fetch = fetch; console.log("ES-Only modules finished loading!"); }Esto le permite llamar a la espera de la carga de los módulos ES-Only una vez y luego usar el módulo más tarde tomándolo de su módulo intermediario de esta manera:
"use strict"; const esmModules = require("esm_modules"); // or whatever you called the intermiary module async function doMyFetching(url, options) { const fetch = esmModules.fetch; const result = await fetch(url, options) }Lo bueno de hacerlo de esta manera es que sabe que sus módulos ES-Only están cargados y sabe que una vez que están cargados puede usarlos a voluntad en el resto de su código de una manera simple y limpia que no No lo obligue a agregar lógica asíncrona adicional por todas partes cada vez que necesite el módulo.
Para solucionar esto, bajé la categoría node-fetch a la última versión 2, que en este momento es 2.6.6. Este es el script que ejecuté:
yarn add node-fetch@^2.6.6 or npm install node-fetch@^2.6.6También agregué estas opciones del compilador:
{ "compilerOptions": { "allowJs": true, "outDir": "./dist" }, }Muchas veces ese error pasa por la versión actual de fetch lo que podemos hacer para solucionarlo, es instalar una versión anterior lo probé y me funcionó.
para instalar la versión anterior: npm i node-fetch@2.6.1 o lo que prefieras.