El uso de Node.js requiere frente a la importación/exportación de ES6
En un proyecto en el que estoy colaborando, tenemos dos opciones sobre qué sistema de módulos podemos usar:
- Importar módulos usando
require
y exportar usandomodule.exports
yexports.foo
. - Importar módulos usando ES6
import
y exportar usando ES6export
¿Existe algún beneficio de rendimiento al usar uno sobre el otro? ¿Hay algo más que debamos saber si usáramos módulos ES6 en lugar de los de Node.js?
Actualizar
Desde Node.js v12 (abril de 2019), la compatibilidad con módulos ES está habilitada de forma predeterminada y desde Node.js v15 (octubre de 2020) es estable (ver aquí ). Los archivos, incluidos los módulos de Node.js, deben terminar en .mjs
o el package.json
archivo más cercano debe contener "type": "module"
. La documentación de Node.js tiene mucha más información, también sobre la interoperabilidad entre los módulos CommonJS y ES.
En cuanto al rendimiento, siempre existe la posibilidad de que las funciones más nuevas no estén tan bien optimizadas como las existentes. Sin embargo, dado que los archivos de módulo sólo se evalúan una vez, es probable que se pueda ignorar el aspecto del rendimiento. Al final, de todos modos hay que ejecutar pruebas comparativas para obtener una respuesta definitiva.
Los módulos ES se pueden cargar dinámicamente a través de la import()
función. A diferencia de require
, esto devuelve una promesa.
Respuesta anterior
¿Existe algún beneficio de rendimiento al usar uno sobre el otro?
Tenga en cuenta que todavía no existe ningún motor JavaScript que admita de forma nativa módulos ES6. Tú mismo dijiste que estás usando Babel . Babel convierte import
y export
declara a CommonJS ( require
/ module.exports
) de forma predeterminada de todos modos. Entonces, incluso si usa la sintaxis del módulo ES6, usará CommonJS internamente si ejecuta el código en Node.js.
Existen diferencias técnicas entre los módulos CommonJS y ES6; por ejemplo, CommonJS le permite cargar módulos dinámicamente. ES6 no permite esto, pero hay una API en desarrollo para eso .
Como los módulos ES6 son parte del estándar, los usaría.
Hay varios usos/capacidades que quizás quieras considerar:
Requerir:
- Puede tener una carga dinámica donde el nombre del módulo cargado no está predefinido/estático, o donde carga condicionalmente un módulo solo si es "realmente necesario" (dependiendo de cierto flujo de código).
- La carga es sincrónica. Eso significa que si tiene varios
require
correos electrónicos, se cargan y procesan uno por uno.
Importaciones ES6:
- Puede utilizar importaciones con nombre para cargar selectivamente solo las piezas que necesita. Eso puede ahorrar memoria.
- La importación puede ser asíncrona (y en el ES6 Module Loader actual, de hecho lo es) y puede funcionar un poco mejor.
Además, el sistema del módulo Require no está basado en estándares. Es muy poco probable que se convierta en estándar ahora que existen los módulos ES6. En el futuro habrá soporte nativo para los módulos ES6 en varias implementaciones, lo que será ventajoso en términos de rendimiento.
A partir de ahora, la importación de ES6 y la exportación siempre se compilan en CommonJS , por lo que no hay ningún beneficio al usar uno u otro. Aunque se recomienda el uso de ES6, ya que debería ser ventajoso cuando se lance el soporte nativo de los navegadores. La razón es que puede importar parciales desde un archivo, mientras que con CommonJS debe requerir todo el archivo.
ES6 →import, export default, export
JS común →require, module.exports, exports.foo
A continuación se muestra el uso común de ellos.
Exportación predeterminada de ES6
// hello.js
function hello() {
return 'hello'
}
export default hello
// app.js
import hello from './hello'
hello() // returns hello
ES6 exporta e importa múltiples
// hello.js
function hello1() {
return 'hello1'
}
function hello2() {
return 'hello2'
}
export { hello1, hello2 }
// app.js
import { hello1, hello2 } from './hello'
hello1() // returns hello1
hello2() // returns hello2
Exportaciones del módulo CommonJS
// hello.js
function hello() {
return 'hello'
}
module.exports = hello
// app.js
const hello = require('./hello')
hello() // returns hello
Módulo CommonJS. Exporta múltiples
// hello.js
function hello1() {
return 'hello1'
}
function hello2() {
return 'hello2'
}
module.exports = {
hello1,
hello2
}
// app.js
const hello = require('./hello')
hello.hello1() // returns hello1
hello.hello2() // returns hello2
Las principales ventajas son sintácticas:
- Sintaxis más declarativa/compacta
- Los módulos ES6 básicamente harán que UMD (Definición de módulo universal) quede obsoleto; esencialmente elimina el cisma entre CommonJS y AMD (servidor versus navegador).
Es poco probable que vea beneficios de rendimiento con los módulos ES6. Aún necesitará una biblioteca adicional para agrupar los módulos, incluso cuando el navegador sea totalmente compatible con las funciones de ES6.
¿Existe algún beneficio de rendimiento al usar uno sobre el otro?
La respuesta actual es no, porque ninguno de los motores de navegador actuales implementa import/export
el estándar ES6.
Algunos cuadros comparativos http://kangax.github.io/compat-table/es6/ no tienen esto en cuenta, así que cuando veas casi todos los verdes para Chrome, ten cuidado. import
La palabra clave de ES6 no se ha tenido en cuenta.
En otras palabras, los motores de navegador actuales, incluido el V8, no pueden importar nuevos archivos JavaScript desde el archivo JavaScript principal mediante ninguna directiva de JavaScript.
(Es posible que todavía falten algunos errores o años hasta que V8 lo implemente de acuerdo con la especificación ES6).
Este documento es lo que necesitamos y este documento es lo que debemos obedecer.
Y el estándar ES6 decía que las dependencias del módulo deberían estar ahí antes de que leamos el módulo como en el lenguaje de programación C, donde teníamos .h
archivos (encabezados).
Esta es una estructura buena y bien probada, y estoy seguro de que los expertos que crearon el estándar ES6 lo tenían en mente.
Esto es lo que permite a Webpack u otros paquetes de paquetes optimizar el paquete en algunos casos especiales y reducir algunas dependencias del paquete que no son necesarias. Pero en los casos en que tenemos dependencias perfectas, esto nunca sucederá.
Se necesitará algo de tiempo hasta que import/export
se active el soporte nativo y la require
palabra clave no desaparecerá durante mucho tiempo.
Qué es require
?
Esta es node.js
la forma de cargar módulos. ( https://github.com/nodejs/node )
Node utiliza métodos a nivel de sistema para leer archivos. Básicamente confías en eso cuando lo usas require
. require
terminará en alguna llamada al sistema como uv_fs_open
(depende del sistema final, Linux, Mac, Windows) para cargar el archivo/módulo JavaScript.
Para comprobar que esto es cierto, intente utilizar Babel.js y verá que la import
palabra clave se convertirá en require
.