La diferencia entre "require (x)" e "import x"

190

Acabo de comenzar a trabajar en un proyecto de nodo pequeño que interactuará con un MongoDB. Sin embargo, parece que no puedo conseguir que los módulos de nodo relevantes se importen correctamente, aunque los haya instalado correctamente a través de npm.

Por ejemplo, el siguiente código arroja un error, diciéndome que "express no tiene exportación predeterminada":

import express from "express";

Sin embargo, este código funciona:

const express = require("express");

Entonces mi pregunta es, ¿cuál es la diferencia en cómo funcionan los métodos de importación y variable / requerimiento? Me gustaría arreglar lo que sea que esté plagando mis importaciones en el proyecto, ya que parece causar problemas adicionales en el futuro.

austinthemassive
fuente
A menos que incluya las definiciones de escritura para express, la primera forma no tendrá sentido, en cuyo caso puede usar la segunda forma, pero la variable expressserá de tipo any. Puede incluir las definiciones desde aquí npmjs.com/package/@types/express
Filipe Sabella

Respuestas:

227

Este diagrama simple que me ayuda a entender la diferencia entre requirey import.

ingrese la descripción de la imagen aquí

Aparte de eso,

No puede cargar selectivamente solo las piezas que necesita, requirepero con imports, puede cargar selectivamente solo las piezas que necesita. Eso puede ahorrar memoria.

La carga es sincrónica (paso a paso) porque, requirepor otro lado, importpuede ser asíncrona (sin esperar la importación previa), por lo que puede funcionar un poco mejor que require .

Siempre soleado
fuente
La mayor diferencia que afecta el código es que las exportaciones en los módulos CommonJS se "calculan", mientras que las exportaciones en un módulo ESM son estáticas (predefinidas). JS puede determinar las exportaciones en un módulo ESM después de solo analizar el código (aún no lo está ejecutando). En un módulo commonJS, las exportaciones solo se conocen cuando el módulo realmente se ejecuta y usted ve a qué se asigna module.exportscuando el código de inicialización del módulo termina de ejecutarse. Esta diferencia por sí sola crea problemas de compatibilidad al tratar de hacer que un solo módulo funcione tanto para ESM como para CommonJS.
jfriend00
Los módulos ESM son más amigables con los paquetes, pero son más restrictivos para los codificadores porque no puede tener exportaciones calculadas en los módulos ESM.
jfriend00
76

La principal diferencia entre requirey import, es que requireescaneará automáticamente node_modulespara encontrar módulos, pero import, que proviene de ES6, no lo hará.

La mayoría de las personas usan babel para compilar importy export, lo que hace que importactúen igual que require.

La versión futura de Node.js podría ser compatible import(en realidad, la versión experimental ya lo es ), y a juzgar por las notas de Node.js, importno será compatible node_modules, se basa en ES6 y debe especificar la ruta del módulo.

Por lo tanto, le sugiero que no lo use importcon babel, pero esta función aún no está confirmada, podría ser compatible node_modulesen el futuro, ¿quién lo sabría?


Como referencia, a continuación se muestra un ejemplo de cómo Babel puede convertir la importsintaxis de ES6 en la sintaxis de CommonJS require.

Digamos que el archivo app_es6.jscontiene esta importación:

import format from 'date-fns/format';

Esta es una directiva para importar la función de formato desde el paquete de nodos date-fns .

El package.jsonarchivo relacionado podría contener algo como esto:

"scripts": {
    "start": "node app.js",
    "build-server-file": "babel app_es6.js --out-file app.js",
    "webpack": "webpack"
}

El .babelrcarchivo relacionado podría ser algo como esto:

{
    "presets": [
        [
            "env",
            {
                "targets":
                {
                    "node": "current"
                }
            }
        ]
    ]
}

Este build-server-filescript definido en el package.jsonarchivo es una directiva para que babel analice el app_es6.jsarchivo y lo muestre app.js.

Después de ejecutar el build-server-filescript, si abre app.jsy busca la date-fnsimportación, verá que se ha convertido en esto:

var _format = require("date-fns/format");

var _format2 = _interopRequireDefault(_format);

La mayor parte de ese archivo es engullido por la mayoría de los humanos, sin embargo, las computadoras lo entienden.


También como referencia, como un ejemplo de cómo se puede crear e importar un módulo en su proyecto, si instala date-fnsy luego abre node_modules/date-fns/get_year/index.js, puede ver que contiene:

var parse = require('../parse/index.js')

function getYear (dirtyDate) {
  var date = parse(dirtyDate)
  var year = date.getFullYear()
  return year
}

module.exports = getYear

Usando el proceso de babel anterior, su app_es6.jsarchivo podría contener:

import getYear from 'date-fns/get_year';

// Which year is 2 July 2014?
var result = getYear(new Date(2014, 6, 2))
//=> 2014

Y Babel convertiría las importaciones a:

var _get_year = require("date-fns/get_year");

var _get_year2 = _interopRequireDefault(_get_year);

Y maneje todas las referencias a la función en consecuencia.

Ayon Lee
fuente
aaaaahhhhhh. Babel no se ha instalado en este proyecto en particular, lo que hace que todo tenga sentido. Pensé que las importaciones / exportaciones de ES6 ya funcionaban, pero ahora entiendo que Babel simplemente está cambiando todo de requiretodos modos
austinthemassive el
se adhieren a exigir por ahora. Siempre puedes cambiarlo en el futuro sin ningún problema
Juan
1
import won't support node_modules¿Que quieres decir con eso?
PrivateOmega
11

Permítanme dar un ejemplo para incluir el módulo express con require & import

-exigir

var express = require('express');

-importar

import * as  express from 'express';

Entonces, después de usar cualquiera de las declaraciones anteriores, tendremos una variable llamada 'express' con nosotros. Ahora podemos definir la variable 'aplicación' como,

var app = express(); 

Entonces usamos 'require' con 'CommonJS' e 'import' con 'ES6'.

Para obtener más información sobre 'requerir' e 'importar', lea los enlaces a continuación.

require - Requiriendo módulos en Node.js: todo lo que necesitas saber

import: una actualización de los módulos ES6 en Node.js

saikiran_hegde
fuente
3

No es una respuesta aquí y más como un comentario, lo siento pero no puedo comentar.

En el nodo V10, puede usar el indicador --experimental-modulespara indicarle a Nodejs que desea usar import. Pero su script de entrada debe terminar con .mjs.

Tenga en cuenta que esto sigue siendo algo experimental y no debe usarse en la producción.

// main.mjs
import utils from './utils.js'
utils.print();
// utils.js
module.exports={
    print:function(){console.log('print called')}
}

Ref. 1 - Nodejs Doc

Ref 2 - problema de github

Tianpeng Xia
fuente
3

nuevo ES6:

'importar' debe usarse con palabras clave 'exportar' para compartir variables / matrices / objetos entre archivos js:

export default myObject;

//....in another file

import myObject from './otherFile.js';

vieja escuela:

'require' debe usarse con 'module.exports'

 module.exports = myObject;

//....in another file

var myObject = require('./otherFile.js');
LaZza
fuente