Різниця між "вимагаю (х)" та "імпортувати х"


192

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

Наприклад, наступний код видає помилку, кажучи мені, що "експрес не має експорту за замовчуванням":

import express from "express";

Однак цей код працює:

const express = require("express");

Отже, моє запитання полягає в тому, яка різниця у тому, як функція імпорту та змінних / вимагає методів? Я хотів би виправити все, що завдає шкоди моєму імпорту проекту, оскільки, здається, це може спричинити додаткові проблеми в дорозі.


Якщо ви не включите визначення набору тексту для експресу, перша форма не матиме сенсу - у цьому випадку ви можете використовувати другу форму, але змінна expressбуде мати тип any. Ви можете включити визначення звідси npmjs.com/package/@types/express
Філіпе Сабелла

Відповіді:


230

Ця проста діаграма, яка допомагає мені зрозуміти різницю між requireі import.

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

Крім того,

Ви не можете вибірково завантажувати лише ті шматки, які вам потрібні, requireале разом із ними imports, ви можете вибірково завантажувати лише потрібні вам частини. Це може зберегти пам'ять.

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


Найбільша різниця, що впливає на код, полягає в тому, що експорт в модулі CommonJS "обчислюється", тоді як експорт в модуль ESM є статичним (заздалегідь визначеним). JS може визначити експорт в модуль ESM, лише проаналізувавши код (ще не запустивши його). У модулі commonJS експорт відомий лише тоді, коли модуль фактично працює, і ви бачите, що призначено, module.exportsколи код ініціалізації модуля закінчується. Сама така різниця створює головні болі сумісності при спробі змусити один модуль працювати як для ESM, так і для CommonJS.
jfriend00

Модулі ESM зручніші для постачальників, але є більш обмежуючими для кодерів, оскільки ви не можете обчислити експорт у модулі ESM.
jfriend00

77

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

Більшість людей використовують дівочих підборців для компіляції importта export, що змушує importдіяти так само, як require.

Майбутня версія Node.js може підтримувати importсебе (насправді експериментальна версія вже є ), і, судячи з приміток Node.js, importне підтримуватиме node_modules, вона базується на ES6, і повинна вказати шлях модуля.

Тож я б запропонував вам не користуватися importбабером, але ця функція ще не підтверджена, вона може підтримувати node_modulesнадалі, хто б це знав?


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

Скажіть, що файл app_es6.jsмістить цей імпорт:

import format from 'date-fns/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

І вавило перетворить імпорт на:

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

var _get_year2 = _interopRequireDefault(_get_year);

І відповідно обробляти всі посилання на функцію.


aaaaahhhhhh. У цьому конкретному проекті Babel не встановлено, що має сенс для всіх. Я думав, що імпорт / експорт ES6 вже функціонують, але тепер я розумію, що Babel все requireодно просто змінить все
austinthemassive

палиця вимагати поки. Ви завжди можете змінити це в майбутньому без будь-яких проблем
Хуан

1
import won't support node_modulesЩо ти мав на увазі під цим?
PrivateOmega

11

Дозвольте навести приклад для включення експрес-модуля з вимагати та імпортувати

-потрібний

var express = require('express');

-імпорт

import * as  express from 'express';

Тож після використання будь-якого з вищезазначених висловлювань у нас буде змінна назва, яка називається "express". Тепер ми можемо визначити змінну "app" як:

var app = express(); 

Таким чином, ми використовуємо 'Requ' з 'CommonJS' та 'import' з 'ES6'.

Для отримання додаткової інформації про "вимагати" та "імпортувати", прочитайте посилання нижче.

вимагають - Потрібні модулі в Node.js: Все, що вам потрібно знати

import - оновлення модулів ES6 в Node.js


3

Тут не відповідь і більше подібний до коментаря, вибачте, але я не можу коментувати.

У вузлі V10 ви можете використовувати прапор, --experimental-modulesщоб повідомити Nodejs, який ви хочете використовувати import. Але ваш сценарій вступу повинен закінчуватися .mjs.

Зауважте, це все-таки експериментальна річ, і її не слід використовувати у виробництві.

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

Ref 1 - Nodejs Doc

Посилання 2 - випуск github


3

новий ES6:

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

export default myObject;

//....in another file

import myObject from './otherFile.js';

старий скол:

"вимагати" слід використовувати з "module.exports"

 module.exports = myObject;

//....in another file

var myObject = require('./otherFile.js');
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.