La differenza tra "richiedono (x)" e "importa x"


190

Ho appena iniziato a lavorare su un progetto a nodo piccolo che si interfaccia con MongoDB. Tuttavia, non riesco a ottenere l'importazione corretta dei moduli nodo rilevanti, anche se li ho installati correttamente tramite npm.

Ad esempio, il codice seguente genera un errore che mi dice che "express non ha esportazione predefinita":

import express from "express";

Tuttavia, questo codice funziona:

const express = require("express");

Quindi la mia domanda è: qual è la differenza nel modo in cui funzionano i metodi di importazione e variabili / richiedono? Vorrei sistemare tutto ciò che affligge le mie importazioni nel progetto, poiché sembra che possa causare ulteriori problemi lungo la strada.


A meno che non includiate le definizioni di battitura per express, il primo modulo non avrà senso - nel qual caso è possibile utilizzare il secondo modulo, ma la variabile expresssarà di tipo any. È possibile includere le definizioni da qui npmjs.com/package/@types/express
Filipe Sabella

Risposte:


227

Questo semplice diagramma che mi aiuta a capire la differenza tra requiree import.

inserisci qui la descrizione dell'immagine

A parte quello,

Non puoi caricare selettivamente solo i pezzi di cui hai bisogno requirema con imports, puoi caricare selettivamente solo i pezzi di cui hai bisogno. Questo può risparmiare memoria.

Il caricamento è sincrono (passo dopo passo), poiché required'altra parte importpuò essere asincrono (senza attendere l'importazione precedente), quindi può essere leggermente migliore di require .


La più grande differenza che influenza il codice è che le esportazioni nei moduli CommonJS sono "calcolate", mentre le esportazioni in un modulo ESM sono statiche (predefinite). JS può determinare le esportazioni in un modulo ESM solo dopo aver analizzato il codice (non ancora in esecuzione). In un modulo commonJS, le esportazioni sono note solo quando il modulo viene effettivamente eseguito e viene visualizzato ciò a module.exportscui è assegnato al termine dell'esecuzione del codice di inizializzazione del modulo. Questa sola differenza crea problemi di compatibilità nel tentativo di far funzionare un singolo modulo sia per ESM che per CommonJS.
jfriend00

I moduli ESM sono più amichevoli con i bundler, ma sono più restrittivi per i programmatori perché non è possibile calcolare le esportazioni nei moduli ESM.
jfriend00

76

La differenza principale tra requiree import, è che requirescansionerà automaticamente node_modulesper trovare i moduli, ma import, che proviene da ES6, no.

Molte persone usano babel per compilare importe export, il che fa importagire allo stesso modo di require.

La versione futura di Node.js potrebbe supportare importse stessa (in realtà, la versione sperimentale già lo fa ) e, a giudicare dalle note di Node.js, importnon supporterà node_modules, si basa su ES6 e deve specificare il percorso del modulo.

Quindi suggerirei di non usarlo importcon Babel, ma questa funzione non è ancora confermata, potrebbe essere supportata node_modulesin futuro, chi lo saprebbe?


Per riferimento, di seguito è riportato un esempio di come Babel può convertire la importsintassi di ES6 in sintassi di CommonJS require.

Supponiamo che il file app_es6.jscontenga questa importazione:

import format from 'date-fns/format';

Questa è una direttiva per importare la funzione di formato dal pacchetto del nodo date-fns .

Il package.jsonfile correlato potrebbe contenere qualcosa del genere:

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

Il .babelrcfile correlato potrebbe essere qualcosa del genere:

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

Questo build-server-filescript definito nel package.jsonfile è una direttiva per babel per analizzare il app_es6.jsfile e generare il file app.js.

Dopo aver eseguito lo build-server-filescript, se apri app.jse cerchi l' date-fnsimportazione, vedrai che è stato convertito in questo:

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

var _format2 = _interopRequireDefault(_format);

La maggior parte di quel file è gobbledygook per la maggior parte degli umani, tuttavia i computer lo comprendono.


Anche come riferimento, come esempio di come un modulo può essere creato e importato nel tuo progetto, se installi date-fnse poi apri node_modules/date-fns/get_year/index.jspuoi vedere che contiene:

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

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

module.exports = getYear

Utilizzando il processo babel sopra, il tuo app_es6.jsfile potrebbe quindi contenere:

import getYear from 'date-fns/get_year';

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

E Babel convertirà le importazioni in:

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

var _get_year2 = _interopRequireDefault(_get_year);

E gestire tutti i riferimenti alla funzione di conseguenza.


aaaaahhhhhh. Babel non è stato installato su questo particolare progetto, il che ha perfettamente senso. Pensavo che le importazioni / esportazioni di ES6 fossero già funzionanti, ma ora capisco che Babel sta cambiando tutto in requireogni modo
austinthemassive,

attenersi a richiedere per ora. Puoi sempre cambiarlo in futuro senza alcun problema
Juan,

1
import won't support node_modulesCosa intendevi con questo?
PrivateOmega

11

Vorrei fare un esempio per l'inclusione del modulo express con request & import

-require

var express = require('express');

-importare

import * as  express from 'express';

Quindi, dopo aver usato una delle affermazioni sopra, avremo una variabile chiamata 'express' con noi. Ora possiamo definire la variabile 'app' come,

var app = express(); 

Quindi usiamo "request" con "CommonJS" e "import" con "ES6".

Per maggiori informazioni su "richiedi" e "importa", leggi i link seguenti.

richiedi - Moduli richiesti in Node.js: tutto ciò che devi sapere

import - Un aggiornamento sui moduli ES6 in Node.js


3

Non una risposta qui e più come un commento, scusa ma non posso commentare.

Nel nodo V10, puoi usare il flag --experimental-modulesper dire a Nodejs che vuoi usare import. Ma il tuo script di ingresso dovrebbe terminare con .mjs.

Nota che questa è ancora una cosa sperimentale e non dovrebbe essere usata in produzione.

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

Rif 1 - Nodejs Doc

Rif. 2 - problema github


3

nuovo ES6:

'import' dovrebbe essere usato con le parole chiave 'export' per condividere variabili / array / oggetti tra i file js:

export default myObject;

//....in another file

import myObject from './otherFile.js';

vecchia scuola:

'request' dovrebbe essere usato con 'module.exports'

 module.exports = myObject;

//....in another file

var myObject = require('./otherFile.js');
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.