Der Unterschied zwischen "require (x)" und "import x"

188

Ich habe gerade angefangen, an einem kleinen Knotenprojekt zu arbeiten, das mit einer MongoDB verbunden wird. Es scheint jedoch nicht möglich zu sein, die relevanten Knotenmodule korrekt zu importieren, obwohl ich sie über korrekt installiert habe npm.

Der folgende Code gibt beispielsweise einen Fehler aus, der besagt, dass "Express keinen Standardexport hat":

import express from "express";

Dieser Code funktioniert jedoch:

const express = require("express");

Meine Frage ist also, was ist der Unterschied in der Funktionsweise der Methoden import und variable / require? Ich möchte das beheben, was meine Importe im Projekt plagt, da es wahrscheinlich später zusätzliche Probleme verursachen wird.

austinthemassive
quelle
Wenn Sie die Typdefinitionen für Express nicht angeben, ist das erste Formular nicht sinnvoll. In diesem Fall können Sie das zweite Formular verwenden, die Variable expressist jedoch vom Typ any. Sie könnten die Definitionen von hier einfügen npmjs.com/package/@types/express
Filipe Sabella
2
Mögliches Duplikat von Using Node.js erfordert vs. ES6 Import / Export
Ryall

Antworten:

222

Dieses einfache Diagramm hilft mir, den Unterschied zwischen requireund zu verstehen import.

Geben Sie hier die Bildbeschreibung ein

Abgesehen davon,

Sie können nicht nur die benötigten Teile selektiv laden, requireaber mit importskönnen Sie nur die benötigten Teile selektiv laden. Das kann Speicherplatz sparen.

Das Laden ist synchron (Schritt für Schritt), da es requireandererseits importasynchron sein kann (ohne auf den vorherigen Import zu warten), sodass es etwas besser als funktioniert require .

Immer sonnig
quelle
Der größte Unterschied, der sich auf Code auswirkt, besteht darin, dass Exporte in CommonJS-Modulen "berechnet" werden, während Exporte in einem ESM-Modul statisch (vordefiniert) sind. JS kann die Exporte in einem ESM-Modul ermitteln, nachdem nur der Code analysiert wurde (noch nicht ausgeführt). In einem commonJS-Modul sind die Exporte nur bekannt, wenn das Modul tatsächlich ausgeführt wird, und Sie sehen, was zugewiesen ist, module.exportswenn der Modulinitialisierungscode beendet ist. Dieser Unterschied allein verursacht Kompatibilitätsprobleme beim Versuch, ein einzelnes Modul sowohl für ESM als auch für CommonJS zum Laufen zu bringen.
jfriend00
ESM-Module sind für Bundler freundlicher, für Codierer jedoch restriktiver, da Sie keine Exporte in ESM-Modulen berechnet haben können.
jfriend00
76

Der Hauptunterschied zwischen requireund besteht darin import, dass requireautomatisch node_modulesnach Modulen importgesucht wird, bei ES6 jedoch nicht.

Die meisten Leute benutzen babel zum kompilieren importund export, was importdas gleiche macht wie require.

Die zukünftige Version von Node.js unterstützt importsich möglicherweise selbst (tatsächlich tut dies die experimentelle Version bereits ), und nach den Notizen von Node.js importwird dies nicht unterstützt node_modules, sie basiert auf ES6 und muss den Pfad des Moduls angeben.

Ich würde also vorschlagen, dass Sie nicht importmit babel verwenden, aber diese Funktion ist noch nicht bestätigt. Sie wird möglicherweise node_modulesin Zukunft unterstützt. Wer würde das wissen?


Im Folgenden finden Sie ein Beispiel dafür, wie babel die ES6- importSyntax in die CommonJS- requireSyntax konvertieren kann .

Angenommen, die Datei app_es6.jsenthält diesen Import:

import format from 'date-fns/format';

Dies ist eine Anweisung zum Importieren der Formatierungsfunktion aus dem Knotenpaket date-fns .

Die zugehörige package.jsonDatei könnte Folgendes enthalten:

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

Die zugehörige .babelrcDatei könnte ungefähr so ​​aussehen:

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

Dieses build-server-filein der package.jsonDatei definierte Skript ist eine Anweisung für babel, die app_es6.jsDatei zu analysieren und die Datei auszugeben app.js.

build-server-fileWenn Sie nach dem Ausführen des Skripts app.jsden date-fnsImport öffnen und suchen , sehen Sie, dass er in diesen konvertiert wurde:

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

var _format2 = _interopRequireDefault(_format);

Der größte Teil dieser Datei ist für die meisten Menschen ein Gobbledy-Buch, aber Computer verstehen es.


Als Referenz dafür, wie ein Modul erstellt und in Ihr Projekt importiert werden kann, können Sie beim Installieren date-fnsund anschließenden Öffnen node_modules/date-fns/get_year/index.jsFolgendes sehen:

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

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

module.exports = getYear

Mit dem oben beschriebenen Babel-Prozess app_es6.jskönnte Ihre Datei dann Folgendes enthalten:

import getYear from 'date-fns/get_year';

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

Und babel würde die Importe umwandeln in:

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

var _get_year2 = _interopRequireDefault(_get_year);

Und behandeln Sie alle Verweise auf die Funktion entsprechend.

Ayon Lee
quelle
aaaaahhhhhh. Babel wurde in diesem speziellen Projekt nicht installiert, was alles sinnvoll macht. Ich dachte, dass ES6-Importe / require
-Exporte
bleiben Sie vorerst zu fordern. Sie können es in Zukunft jederzeit problemlos ändern
Juan
1
import won't support node_modulesWas wolltest du damit sagen?
PrivateOmega
11

Lassen Sie mich ein Beispiel für das Einschließen eines Express-Moduls mit require & import geben

-benötigen

var express = require('express');

-importieren

import * as  express from 'express';

Nachdem wir eine der obigen Anweisungen verwendet haben, haben wir eine Variable namens 'express' bei uns. Jetzt können wir die 'App'-Variable definieren als:

var app = express(); 

Also verwenden wir 'require' mit 'CommonJS' und 'import' mit 'ES6'.

Weitere Informationen zu "erfordern" und "importieren" finden Sie unter den folgenden Links.

require - Erforderliche Module in Node.js: Alles, was Sie wissen müssen

import - Ein Update zu ES6-Modulen in Node.js.

saikiran_hegde
quelle
3

Keine Antwort hier und eher wie ein Kommentar, sorry, aber ich kann nicht kommentieren.

In Knoten V10 können Sie das Flag verwenden --experimental-modules, um Nodejs mitzuteilen, die Sie verwenden möchten import. Ihr Eingabeskript sollte jedoch mit enden .mjs.

Beachten Sie, dass dies immer noch eine experimentelle Sache ist und nicht in der Produktion verwendet werden sollte.

// 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 - Github-Ausgabe

Tianpeng. Xia
quelle
3

neuer ES6:

'import' sollte mit 'export'-Schlüsselwörtern verwendet werden, um Variablen / Arrays / Objekte zwischen js-Dateien zu teilen:

export default myObject;

//....in another file

import myObject from './otherFile.js';

alte Schule:

'require' sollte mit 'module.exports' verwendet werden.

 module.exports = myObject;

//....in another file

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