it-swarm.com.ru

Использование Node.js требует ES6 импорта / экспорта

В проекте, над которым я работаю, у нас есть два варианта использования модульной системы:

  1. Импорт модулей с использованием require и экспорт с использованием module.exports и exports.foo.
  2. Импорт модулей с использованием ES6 import и экспорт с использованием ES6 export

Есть ли какие-либо преимущества в производительности при использовании одного над другим? Есть ли что-то еще, что мы должны знать, если бы мы использовали модули ES6 над Node?

752
kpimov

Есть ли какие-либо преимущества в производительности при использовании одного над другим?

Имейте в виду, что еще нет движка JavaScript, который изначально поддерживает модули ES6. Вы сами сказали, что используете Вавилон. В любом случае, Babel по умолчанию преобразует объявления import и export в CommonJS (require/module.exports). Так что даже если вы используете синтаксис модуля ES6, вы будете использовать CommonJS под капотом, если будете запускать код в Node.

Существуют технические различия между модулями CommonJS и ES6, например, CommonJS позволяет загружать модули динамически. ES6 не позволяет этого, но для этого есть API .

Поскольку модули ES6 являются частью стандарта, я бы их использовал.

617
Felix Kling

Есть несколько вариантов использования/возможностей, которые вы можете рассмотреть:

Требуется:

  • Вы можете иметь динамическую загрузку, когда имя загруженного модуля не является предопределенным/статическим, или если вы условно загружаете модуль, только если он "действительно требуется" (в зависимости от определенного потока кода).
  • Загрузка синхронная. Это означает, что если у вас есть несколько requires, они загружаются и обрабатываются по одному.

ES6 Импорт:

  • Вы можете использовать именованный импорт, чтобы выборочно загрузить только те части, которые вам нужны. Это может сохранить память.
  • Импорт может быть асинхронным (и в текущем ES6 Module Loader это действительно так) и может работать немного лучше.

Кроме того, система модулей Require не основана на стандартах. Маловероятно, что он станет стандартом сейчас, когда существуют модули ES6. В будущем будет встроена поддержка модулей ES6 в различных реализациях, что будет выгодно с точки зрения производительности.

148
Amit

Основные преимущества синтаксические:

  • Более декларативный/компактный синтаксис
  • Модули ES6 в основном сделают UMD (определение универсального модуля) устаревшим - по сути, устранит раскол между CommonJS и AMD (сервер против браузера).

Вы вряд ли увидите какие-либо преимущества в производительности с модулями ES6. Вам по-прежнему понадобится дополнительная библиотека для объединения модулей, даже если в браузере имеется полная поддержка функций ES6.

36
snozza

Есть ли какие-либо преимущества в производительности при использовании одного над другим?

Текущий ответ - нет, потому что ни один из текущих браузерных движков не реализует import/export из стандарта ES6.

Некоторые таблицы сравнения http://kangax.github.io/compat-table/es6/ не учитывают это, поэтому, когда вы видите почти все зеленые цвета для Chrome, просто будьте осторожны. Ключевое слово import из ES6 не было учтено.

Другими словами, современные движки браузера, включая V8, не могут импортировать новый файл JavaScript из основного файла JavaScript через любую директиву JavaScript.

(Возможно, мы еще просто несколько ошибок или через несколько лет, пока V8 не реализует это в соответствии со спецификацией ES6.)

Это документ - это то, что нам нужно, и это документ - это то, что мы должны соблюдать.

И в стандарте ES6 сказано, что зависимости модуля должны существовать до того, как мы прочитаем модуль, как на языке программирования C, где у нас были (заголовочные файлы) .h файлы.

Это хорошая и хорошо протестированная структура, и я уверен, что эксперты, создавшие стандарт ES6, имели это в виду.

Это то, что позволяет Webpack или другим пакетным пакетам оптимизировать пакет в некоторых особых случаях и уменьшить некоторые ненужные зависимости от пакета. Но в тех случаях, когда у нас есть идеальные зависимости, этого никогда не произойдет.

Потребуется некоторое время, пока не будет запущена нативная поддержка import/export, и ключевое слово require никуда не денется в течение длительного времени.

Что такое require?

Это node.js способ загрузки модулей. ( https://github.com/nodejs/node )

Узел использует системные методы для чтения файлов. Вы в основном полагаетесь на это при использовании require. require завершится некоторым системным вызовом, таким как uv_fs_open (зависит от конечной системы, Linux, Mac, Windows) для загрузки файла/модуля JavaScript.

Чтобы убедиться, что это правда, попробуйте использовать Babel.js, и вы увидите, что ключевое слово import будет преобразовано в require.

enter image description here

30
prosti

Использование модулей ES6 может быть полезно для "тряски деревьев"; то есть, позволяя Webpack 2, Rollup (или другим упаковщикам) идентифицировать пути кода, которые не используются/не импортируются, и, следовательно, не превращать их в результирующий пакет. Это может значительно уменьшить размер файла за счет исключения кода, который вам никогда не понадобится, но с CommonJS по умолчанию связан, потому что Webpack и другие не имеют возможности узнать, нужен ли он.

Это делается с помощью статического анализа пути кода.

Например, используя:

import { somePart } 'of/a/package';

... дает сборщику подсказку, что package.anotherPart не требуется (если он не импортирован, его нельзя использовать, верно?), так что он не будет мешать его связыванию.

Чтобы включить это для Webpack 2, вам нужно убедиться, что ваш транспортер не выплевывает модули CommonJS. Если вы используете плагин es2015 с babel, вы можете отключить его в своем .babelrc следующим образом:

{
  "presets": [
    ["es2015", { modules: false }],
  ]
}

Свернуть и другие могут работать по-другому - просмотрите документы, если вам интересно.

28
Lee Benson

Когда дело доходит до асинхронной или, возможно, отложенной загрузки, тогда import () гораздо более мощный. Посмотрите, когда нам требуется компонент асинхронным способом, тогда мы используем import в некотором асинхронном режиме, как в переменной const, используя await.

const module = await import('./module.js');

Или, если вы хотите использовать require() тогда,

const converter = require('./converter');

Дело в том, что import() на самом деле асинхронный характер. Как упомянуто neehar venugopal в ReactConf , вы можете использовать его для динамической загрузки реагирующих компонентов для архитектуры на стороне клиента.

Также это намного лучше, когда речь идет о маршрутизации. Это единственная особенность, которая заставляет сетевой журнал загружать необходимую часть, когда пользователь подключается к определенному веб-сайту к его конкретному компоненту. например Страница входа в систему до панели инструментов не будет загружать все компоненты панели инструментов. Потому что то, что нужно в данный момент, то есть компонент входа, будет загружено только.

То же самое касается export: ES6 export точно такие же, как и для CommonJS module.exports.

NOTE - если вы разрабатываете проект node.js, то вы должны строго использовать require() в качестве узла выдаст ошибку исключения как invalid token 'import', если вы будете использовать import. Таким образом, узел не поддерживает операторы импорта.

ОБНОВЛЕНИЕ - В соответствии с предложением Дэн Даскалеску : Начиная с версии 8.5 (выпущено в сентябре 2017 г.), node --experimental-modules index.mjs позволяет вам использовать import без Babel. Вы можете (и должны) также опубликовать свои пакеты npm как собственный ESModule с обратной совместимостью для старого способа require.

Посмотрите это, чтобы больше узнать, где использовать асинхронный импорт - https://www.youtube.com/watch?v=bb6RCrDaxhw

14
Meet Zaveri

Я лично использую импорт, потому что мы можем импортировать необходимые методы, члены, используя импорт.

import {foo, bar} from "dep";

FileName: dep.js

export foo function(){};
export const bar = 22

Кредит идет на Пола Шана. Подробнее .

5
chandoo

Самое важное, что нужно знать, это то, что модули ES6 действительно являются официальным стандартом, а модули CommonJS (Node.js) - нет.

В 2019 году модули ES6 поддерживаются 84% браузерами. В то время как Node.js помещает их за флагом - экспериментальные модули , существует также удобный пакет узлов, называемый esm , который делает интеграцию гладкой.

Другая проблема, с которой вы можете столкнуться между этими модульными системами, - это местоположение кода. Node.js предполагает, что источник хранится в каталоге node_modules, в то время как большинство модулей ES6 развернуто в структуре плоского каталога. Их нелегко согласовать, но это можно сделать, взломав файл package.json с помощью сценариев до и после установки. Вот пример изоморфный модуль и статья , объясняющий, как это работает.

4
isysd