La différence entre "require (x)" et "import x"

193

Je viens de commencer à travailler sur un petit projet de nœud qui s'interface avec un MongoDB. Cependant, je n'arrive pas à faire importer correctement les modules de nœuds concernés, même si je les ai installés correctement via npm.

Par exemple, le code suivant génère une erreur, m'indiquant que "express n'a pas d'export par défaut":

import express from "express";

Cependant, ce code fonctionne:

const express = require("express");

Ma question est donc la suivante: quelle est la différence dans le fonctionnement des méthodes d'importation et de variable / require? Je voudrais résoudre ce qui affecte mes importations sur le projet, car cela semble susceptible de causer des problèmes supplémentaires sur la route.

austinthemassif
la source
À moins que vous n'incluiez les définitions de saisie pour express, le premier formulaire n'aura aucun sens - dans ce cas, vous pouvez utiliser le second formulaire, mais la variable expresssera de type any. Vous pouvez inclure les définitions d'ici npmjs.com/package/@types/express
Filipe Sabella

Réponses:

233

Ce schéma simple qui m'aide à comprendre la différence entre requireet import.

entrez la description de l'image ici

Mis à part cela,

Vous ne pouvez pas charger sélectivement uniquement les pièces dont vous avez besoin, requiremais avec imports, vous pouvez charger sélectivement uniquement les pièces dont vous avez besoin. Cela peut économiser de la mémoire.

Le chargement est synchrone (étape par étape) car requirepar contre importpeut être asynchrone (sans attendre l'importation précédente) donc il peut fonctionner un peu mieux que require .

Toujours ensoleillé
la source
La plus grande différence qui affecte le code est que les exportations dans les modules CommonJS sont "calculées", alors que les exportations dans un module ESM sont statiques (prédéfinies). JS peut déterminer les exportations dans un module ESM uniquement après avoir analysé le code (sans l'exécuter encore). Dans un module commonJS, les exportations ne sont connues que lorsque le module s'exécute réellement et que vous voyez ce qui est affecté à module.exportsla fin de l'exécution du code d'initialisation du module. Cette seule différence crée des problèmes de compatibilité en essayant de faire fonctionner un seul module pour ESM et CommonJS.
jfriend00
Les modules ESM sont plus conviviaux pour les bundlers, mais sont plus restrictifs pour les codeurs car vous ne pouvez pas avoir calculé les exportations dans les modules ESM.
jfriend00
77

La principale différence entre requireet import, est que requirele scanne automatiquement node_modulespour trouver des modules, mais import, qui vient d'ES6, ne le fera pas.

La plupart des gens utilisent babel pour compiler importet export, ce qui fait importagir de la même manière que require.

La future version de Node.js pourrait prendre importen charge elle-même (en fait, la version expérimentale le fait déjà ), et à en juger par les notes de Node.js, importne prend pas en charge node_modules, elle est basée sur ES6 et doit spécifier le chemin du module.

Je vous suggère donc de ne pas l'utiliser importavec babel, mais cette fonctionnalité n'est pas encore confirmée, elle pourrait prendre node_modulesen charge dans le futur, qui le saurait?


Pour référence, vous trouverez ci-dessous un exemple de la façon dont babel peut convertir la importsyntaxe d' ES6 en syntaxe de CommonJS require.

Disons que le fichier app_es6.jscontient cette importation:

import format from 'date-fns/format';

Il s'agit d'une directive pour importer la fonction de format à partir du package de nœuds date-fns .

Le package.jsonfichier associé pourrait contenir quelque chose comme ceci:

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

Le .babelrcfichier associé pourrait être quelque chose comme ceci:

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

Ce build-server-filescript défini dans le package.jsonfichier est une directive permettant à babel d'analyser le app_es6.jsfichier et de sortir le fichier app.js.

Après avoir exécuté le build-server-filescript, si vous ouvrez app.jset recherchez l' date-fnsimportation, vous verrez qu'elle a été convertie en ceci:

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

var _format2 = _interopRequireDefault(_format);

La plupart de ce fichier est englouti par la plupart des humains, mais les ordinateurs le comprennent.


Aussi pour référence, comme exemple de la façon dont un module peut être créé et importé dans votre projet, si vous installez date-fnspuis ouvrez, node_modules/date-fns/get_year/index.jsvous pouvez voir qu'il contient:

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

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

module.exports = getYear

En utilisant le processus babel ci-dessus, votre app_es6.jsfichier pourrait alors contenir:

import getYear from 'date-fns/get_year';

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

Et babel convertirait les importations en:

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

var _get_year2 = _interopRequireDefault(_get_year);

Et gérez toutes les références à la fonction en conséquence.

Ayon Lee
la source
aaaaahhhhhh. Babel n'a pas été installé sur ce projet particulier, ce qui fait que tout a du sens. Je pensais que les importations / exportations ES6 étaient déjà fonctionnelles, mais maintenant je comprends que Babel est en train de tout changer de requiretoute façon
austinthemassive
s'en tenir à exiger pour l'instant. Vous pouvez toujours le changer à l'avenir sans aucun problème
Juan
2
import won't support node_modulesQu'est-ce que vous entendez par là?
PrivateOmega
11

Permettez-moi de donner un exemple pour inclure le module express avec require & import

-exiger

var express = require('express');

-importer

import * as  express from 'express';

Donc, après avoir utilisé l'une des instructions ci-dessus, nous aurons une variable appelée «express» avec nous. Maintenant, nous pouvons définir la variable 'app' comme suit:

var app = express(); 

Nous utilisons donc «require» avec «CommonJS» et «import» avec «ES6».

Pour plus d'informations sur «exiger» et «importer», lisez les liens ci-dessous.

require - Modules requis dans Node.js: tout ce que vous devez savoir

import - Une mise à jour sur les modules ES6 dans Node.js

saikiran_hegde
la source
3

Pas une réponse ici et plutôt un commentaire, désolé mais je ne peux pas commenter.

Dans le nœud V10, vous pouvez utiliser l'indicateur --experimental-modulespour indiquer à Nodejs que vous souhaitez utiliser import. Mais votre script d'entrée doit se terminer par .mjs.

Notez que ceci est encore une chose expérimentale et ne doit pas être utilisé en production.

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

Réf 1 - Nodejs Doc

Ref 2 - Problème Github

Tianpeng. Xia
la source
3

nouveau ES6:

'import' doit être utilisé avec les mots clés 'export' pour partager des variables / tableaux / objets entre des fichiers js:

export default myObject;

//....in another file

import myObject from './otherFile.js';

vieille école:

'require' doit être utilisé avec 'module.exports'

 module.exports = myObject;

//....in another file

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