В проекте, над которым я работаю, у нас есть два варианта использования модульной системы:
- Импорт модулей с использованием
require
и экспорт с использованиемmodule.exports
иexports.foo
. - Импорт модулей с использованием ES6
import
и экспорт с использованием ES6export
Есть ли преимущества в производительности при использовании одного над другим? Есть ли что-то еще, что мы должны знать, если бы мы использовали модули ES6 вместо узлов?
javascript
node.js
ecmascript-6
babeljs
kpimov
источник
источник
node --experimental-modules index.mjs
позволяет использоватьimport
без Babel и работает в Node 8.5.0+. Вы можете (и должны) также публиковать свои пакеты npm как нативный ESModule с обратной совместимостью по старомуrequire
.Ответы:
Имейте в виду, что еще нет движка JavaScript, который изначально поддерживает модули ES6. Вы сами сказали, что используете Вавилон. В любом случае Babel по умолчанию конвертирует
import
иexport
объявляет в CommonJS (require
/module.exports
). Так что даже если вы используете синтаксис модуля ES6, вы будете использовать CommonJS под капотом, если будете запускать код в Node.Существуют технические различия между модулями CommonJS и ES6, например, CommonJS позволяет динамически загружать модули. ES6 не позволяет этого, но для этого существует API .
Поскольку модули ES6 являются частью стандарта, я бы их использовал.
источник
ES6 import
с,require
но они работали по-другому. CommonJS экспортирует сам класс, пока существует только один класс. ES6 экспортирует, как будто есть несколько классов, поэтому вы должны использовать,.ClassName
чтобы получить экспортируемый класс. Есть ли другие различия, которые на самом деле влияют на реализациюmodule.exports = ...;
эквивалентноexport default ...
.exports.foo = ...
эквивалентноexport var foo = ...
;import
на CommonJS в Node, который используется вместе с Webpack 2 / Rollup (и любым другим упаковщиком, который позволяет встряхивать дерево ES6), возможно, что файл окажется значительно меньше, чем эквивалентный код, который Node хрустит благодаря использованиюrequire
именно из- за того, что ES6 позволяет проводить статический анализ импорта / экспорта. Хотя это и не будет иметь никакого значения для Node (пока), это, безусловно, может, если код в конечном итоге окажется в виде единого пакета браузера.Есть несколько вариантов использования / возможностей, которые вы можете рассмотреть:
Требуется:
require
s, они загружаются и обрабатываются по одному.ES6 Импорт:
Кроме того, система модулей Require не основана на стандартах. Маловероятно, что он станет стандартом сейчас, когда существуют модули ES6. В будущем будет встроена поддержка модулей ES6 в различных реализациях, что будет выгодно с точки зрения производительности.
источник
require
любом случае, поэтому вы все равно используете систему модулей и загрузчик Node.Основные преимущества синтаксические:
Вы вряд ли увидите какие-либо преимущества в производительности с модулями ES6. Вам по-прежнему понадобится дополнительная библиотека для объединения модулей, даже если в браузере имеется полная поддержка функций ES6.
источник
node --experimemntal-modules index.mjs
использоватьimport
без Babel. Вы можете (и должны) также публиковать свои пакеты npm как нативный ESModule с обратной совместимостью по старомуrequire
. Многие браузеры также поддерживают динамический импорт .Текущий ответ - нет, потому что ни один из текущих браузерных движков не реализует
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
.источник
import
в процессе сборки Webpack 2 / Rollup может потенциально уменьшить размер получаемого файла путем «встряхивания дерева» неиспользуемых модулей / кода, которые в противном случае могут оказаться в конечном пакете. Меньший размер файла = быстрее загружать = быстрее инициализировать / выполнять на клиенте.import
ключевое слово изначально Или это означает, что вы не можете импортировать другой файл JavaScript из файла JavaScript. Вот почему вы не можете сравнить преимущества производительности этих двух. Но, конечно, такие инструменты, как Webpack1 / 2 или Browserify, могут справиться со сжатием. Они шеи на шею: gist.github.com/substack/68f8d502be42d5cd4942import
иexport
являются статическими объявлениями, которые импортируют определенный путь кода, тогда какrequire
могут быть динамическими и, следовательно, связываться в коде, который не используется. Выигрыш в производительности косвенный - Webpack 2 и / или Rollup могут потенциально привести к меньшему размеру пакета, который быстрее загружается и, следовательно, кажется более быстрым для конечного пользователя (браузера). Это работает, только если весь код написан в модулях ES6 и, следовательно, импорт может быть подвергнут статическому анализу.import/export
переделаноrequire
, предоставлено. Но то, что происходит перед этим шагом, можно считать повышением производительности. Пример: еслиlodash
написано в ES6, и выimport { omit } from lodash
, окончательный комплект будет содержать ТОЛЬКО «Пропустить», а не другие утилиты, тогда как простоеrequire('lodash')
импортирует все. Это увеличит размер пакета, займет больше времени для загрузки и, следовательно, снизит производительность. Конечно, это действительно только в контексте браузера.Использование модулей ES6 может быть полезно для «тряски деревьев»; т.е. позволяя Webpack 2, Rollup (или другим упаковщикам) идентифицировать пути кода, которые не используются / не импортируются, и, следовательно, не попадают в результирующий пакет. Это может значительно уменьшить размер файла за счет исключения кода, который вам никогда не понадобится, но с CommonJS по умолчанию связан, потому что Webpack и другие не имеют возможности узнать, нужен ли он.
Это делается с помощью статического анализа пути кода.
Например, используя:
... дает сборщику подсказку, которая
package.anotherPart
не требуется (если она не импортирована, ее нельзя использовать, верно?), так что она не будет мешать ее объединению.Чтобы включить это для Webpack 2, вам нужно убедиться, что ваш транспортер не выплевывает модули CommonJS. Если вы используете
es2015
плагин с babel, вы можете отключить его.babelrc
следующим образом:Свернуть и другие могут работать по-другому - просматривать документы, если вы заинтересованы.
источник
Когда дело доходит до асинхронной или, может быть, ленивой загрузки, то
import ()
она гораздо мощнее. Посмотрите, когда нам требуется компонент асинхронным способом, тогда мы используемimport
его некоторым асинхронным способом, как приconst
использовании переменнойawait
.Или если вы хотите использовать
require()
тогда,Дело в том,
import()
что на самом деле это асинхронный характер. Как упоминает neehar venugopal в ReactConf , вы можете использовать его для динамической загрузки реагирующих компонентов для архитектуры на стороне клиента.Также это намного лучше, когда речь идет о маршрутизации. Это единственная особенность, которая заставляет сетевой журнал загружать необходимую часть, когда пользователь подключается к определенному веб-сайту к его конкретному компоненту. Например, страница входа перед панелью управления не будет загружать все компоненты панели мониторинга. Потому что то, что нужно текущему, то есть компоненту входа, которое будет загружено только.
То же самое касается
export
: ES6export
точно так же, как для CommonJSmodule.exports
.ПРИМЕЧАНИЕ. - Если вы разрабатываете проект 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.
источник
Самое важное, что нужно знать, это то, что модули ES6 действительно являются официальным стандартом, а модули CommonJS (Node.js) - нет.
В 2019 году модули ES6 поддерживаются 84% браузеров. В то время как Node.js помещает их за флаг --experimental-modules , есть также удобный пакет узлов, называемый esm , который делает интеграцию гладкой.
Другая проблема, с которой вы можете столкнуться между этими модульными системами, - это местоположение кода. Node.js предполагает, что источник хранится в
node_modules
каталоге, в то время как большинство модулей ES6 развернуто в плоской структуре каталогов. Это нелегко согласовать, но это можно сделать, взломавpackage.json
файл с помощью сценариев до и после установки. Вот пример изоморфного модуля и статья, объясняющая, как он работает.источник
Я лично использую импорт, потому что мы можем импортировать необходимые методы, члены, используя импорт.
Имя файла : dep.js
Кредит идет на Пола Шана. Более подробная информация .
источник
require
?const {a,b} = require('module.js');
работает также ... если вы экспортируетеa
иb
module.exports = { a: ()={}, b: 22 }
- Вторая часть @BananaAcid отвечаетНа данный момент импорт ES6, экспорт всегда компилируется в CommonJS , поэтому использование того или другого не имеет смысла . Хотя использование ES6 рекомендуется, так как оно должно быть выгодно, когда выпущена встроенная поддержка браузеров. Причина в том, что вы можете импортировать партиалы из одного файла, в то время как с CommonJS вам потребуется весь файл.
ES6 →
import, export default, export
CommonJS →
require, module.exports, exports.foo
Ниже приводится общее использование тех.
ES6 экспорт по умолчанию
ES6 экспортировать несколько и импортировать несколько
CommonJS module.exports
CommonJS module.exports несколько
источник
Не уверен, почему (возможно, оптимизация - ленивая загрузка?) Это работает так, но я заметил, что
import
может не анализировать код, если импортированные модули не используются.Который не может быть ожидаемым поведением в некоторых случаях.
Возьмите ненавистный класс Foo в качестве нашего примера зависимости.
foo.ts
Например:
index.ts
index.ts
index.ts
С другой стороны:
index.ts
источник