Разница между require (x) и import x

Я только начал работать над небольшим проектом узла, который будет взаимодействовать с MongoDB. Однако мне кажется, что мне не удается правильно импортировать соответствующие модули узлов, хотя я правильно их установил через npm.

Например, следующий код выдает ошибку, сообщая мне, что «экспресс не имеет экспорта по умолчанию»:

import express from "express";

Однако этот код работает:

const express = require("express");

Итак, мой вопрос: в чем разница в том, как работают методы import и variable / require? Я хотел бы исправить все, что мешает моему импорту в проекте, поскольку это может вызвать дополнительные проблемы. по дороге.


person austinthemassive    schedule 11.10.2017    source источник
comment
Если вы не включите определения набора для выражения express, первая форма не будет иметь смысла - в этом случае вы можете использовать вторую форму, но переменная express будет иметь тип any. Вы можете включить определения отсюда npmjs.com/package/@types/express   -  person fs_    schedule 11.10.2017
comment
@Ryall, это другой вопрос. Обратите внимание, что import x = require('x') - это не то же самое, что var x = require('x').   -  person Tomasz Gawel    schedule 24.11.2020


Ответы (5)


Эта простая диаграмма помогает мне понять разницу между require и import.

введите описание изображения здесь

Кроме того,

Вы не можете выборочно загружать только те элементы, которые вам нужны, с помощью require, но с imports вы можете выборочно загружать только те элементы, которые вам нужны. Это может сэкономить память.

Загрузка выполняется синхронно (шаг за шагом) для require, с другой стороны, import может быть асинхронным (без ожидания предыдущего импорта), поэтому может работать немного лучше, чем require.

person Always Sunny    schedule 11.10.2017
comment
Самая большая разница, которая влияет на код, заключается в том, что экспорт в модулях CommonJS вычисляется, тогда как экспорт в модуле ESM является статическим (предварительно определенным). JS может определять экспорт в модуле ESM только после синтаксического анализа кода (еще не запуска его). В модуле commonJS экспорт становится известен только тогда, когда модуль действительно запускается, и вы видите, что присвоено module.exports, когда завершается выполнение кода инициализации модуля. Одно это различие создает проблемы совместимости при попытке заставить один модуль работать как для ESM, так и для CommonJS. - person jfriend00; 05.06.2020
comment
Модули ESM более удобны для сборщиков, но более ограничены для кодеров, потому что вы не можете иметь вычисленный экспорт в модулях ESM. - person jfriend00; 05.06.2020

Основное различие между require и import состоит в том, что require будет автоматически сканировать node_modules для поиска модулей, а import, который исходит от ES6, не будет.

Большинство людей используют babel для компиляции import и export, что заставляет import действовать так же, как require.

Будущая версия Node.js может поддерживать сам import (на самом деле экспериментальная версия уже поддерживает), и, судя по Node.js, примечания, import не будет поддерживать node_modules, он основан на ES6 и должен указывать путь к модулю.

Поэтому я бы посоветовал вам не использовать import с babel, но эта функция еще не подтверждена, она может поддерживать node_modules в будущем, кто знает?


Для справки ниже приведен пример того, как babel может преобразовать синтаксис import ES6 в синтаксис require CommonJS.

Скажем, fileapp_es6.js содержит этот импорт:

import format from 'date-fns/format';

Это директива для импорта функции format из пакета узла date-fns.

Соответствующий файл package.json может содержать что-то вроде этого:

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

Соответствующий файл .babelrc может быть примерно таким:

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

Этот build-server-file сценарий, определенный в package.json файле, является директивой для babel, чтобы проанализировать app_es6.js файл и вывести файл app.js.

Если после запуска build-server-file скрипта вы откроете app.js и найдете импорт date-fns, вы увидите, что он был преобразован в этот:

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

var _format2 = _interopRequireDefault(_format);

Большая часть этого файла - чепуха для большинства людей, хотя компьютеры это понимают.


Также для справки, в качестве примера того, как модуль может быть создан и импортирован в ваш проект, если вы установите date-fns, а затем откроете node_modules/date-fns/get_year/index.js, вы увидите, что он содержит:

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

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

module.exports = getYear

Используя описанный выше процесс babel, ваш app_es6.js файл может содержать:

import getYear from 'date-fns/get_year';

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

И babel преобразовал бы импорт в:

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

var _get_year2 = _interopRequireDefault(_get_year);

И обработайте все ссылки на функцию соответствующим образом.

person A-yon Lee    schedule 11.10.2017
comment
ааааахххххх. В этом конкретном проекте Babel не был установлен, поэтому все имеет смысл. Я думал, что импорт / экспорт ES6 уже работает, но теперь я понимаю, что Babel все равно меняет все на require - person austinthemassive; 12.10.2017
comment
придерживайтесь требования на данный момент. Вы всегда можете поменять его в будущем без проблем - person Juan; 20.04.2018
comment
import won't support node_modules Что вы имели в виду? - person PrivateOmega; 11.04.2019
comment
import и require оба сканируют node_modules пакет, указанный в операторе. require загружает все, что назначено module.exports в пакете, в переменную, которой оно присвоено, или в глобальную область видимости, если левая рука не объявлена. Однако import будет загружать экспорт es6 по умолчанию только по имени, если все они не назначены псевдониму: import * as X from 'pkg'. Вы можете импортировать пакеты es6 без значений по умолчанию, используя также деструктуризацию объекта: import { X } from 'pkg'. Он будет работать так же, как require, если вы импортируете весь пакет, включая все экспорты, в глобальную область import 'package'. - person Rik; 04.12.2020

Позвольте мне привести пример включения экспресс-модуля с требованием и импортом

-требовать

var express = require('express');

-Импортировать

import * as  express from 'express';

Итак, после использования любого из приведенных выше операторов у нас будет переменная с именем «express». Теперь мы можем определить переменную app как

var app = express(); 

Поэтому мы используем require с CommonJS и import с ES6.

Для получения дополнительной информации о «требовать» и «импортировать» прочтите ссылки ниже.

require - Требование модулей в Node. js: все, что вам нужно знать

import - Обновление по Модули ES6 в Node.js

person saikiran_hegde    schedule 09.08.2018
comment
Это определенно правильный ответ. У автора сообщения возникла проблема с использованием инструкции es6 import, и его смутила ошибка express не имеет экспорта по умолчанию. Этот ответ дает решение. Модули с множественными (и даже одиночными) экспортами, которые не определяют default export, должны будут иметь все экспорты, назначенные именованной переменной, как объясняется в ответе: import * as whatever from 'package'; - person Rik; 04.12.2020

Я сделаю это просто,

  • Импорт и экспорт - это функции ES6 (JS следующего поколения).
  • Require - это старый метод импорта кода из других файлов.

Основное отличие состоит в том, что требуется, вызывается или импортируется весь JS-файл. Даже если вам не нужна какая-то его часть.

var myObject = require('./otherFile.js'); //This JS file will be imported fully.

В то время как при импорте вы можете извлекать только необходимые объекты / функции / переменные.

import { getDate }from './utils.js'; 
//Here I am only pulling getDate method from the file instead of importing full file

Еще одно важное отличие состоит в том, что вы можете использовать require в любом месте программы, где import всегда должен быть в верхней части файла.

person pranav shinde    schedule 16.11.2020
comment
Вы можете использовать деструктуризацию объекта с require, например. const { getDate } = require('./utils.js'); - person d512; 11.05.2021
comment
Да, в последних версиях узлов мы можем использовать, но в более ранних версиях этого не было. - person pranav shinde; 11.05.2021
comment
Начиная с версии 6 (апрель 2016 г.) деструктурированный импорт поддерживается в Node. - person Developer Dave; 28.06.2021
comment
Ваше общее объяснение слишком простое и неточное. Даже заявление об использовании require в любом месте программы, в то время как import только в верхней части файла, скрывает важные детали. Когда вы используете require в области видимости функции (или области блока где-то в коде приложения), а не в области модуля / файла, это имеет эквивалент с модулями ES (также известный как синтаксис import). Однако это асинхронная операция, и для этого динамического импорта необходимо использовать ключевое слово .then() или await. - person Developer Dave; 28.06.2021

новый ES6:

'import' следует использовать с ключевыми словами 'export' для обмена переменными / массивами / объектами между файлами js:

export default myObject;

//....in another file

import myObject from './otherFile.js';

старая школа:

'require' следует использовать с 'module.exports'

 module.exports = myObject;

//....in another file

var myObject = require('./otherFile.js');
person LaZza    schedule 26.11.2019