javascript - это - загрузчик модулей js




Учитывая ES2015, инъекцию зависимостей и абстракцию библиотеки, какой должен быть мой идеальный модуль в 2016 году? (2)

Если нет, с одной стороны, я буду на борту для написания всех моих модулей, таких как

import A from './a.js';

var B = function(){
  //use A
};

export default B;

а затем с помощью компилятора для его создания в какой-либо формат браузера или сервера.

Однако моя проблема с вышеизложенным заключается в явной спецификации ./a.js в import .

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

  1. Как уже было сказано выше, при частом переработке модулей из проекта в проект очень вероятно, что вы не сможете поддерживать согласованный путь к этому ресурсу в своем дереве проектов. Выпечка вызова import myModule from './../../vendor/lib/dist/mod.js' как import myModule from './../../vendor/lib/dist/mod.js' в код модуля, не совсем точно import myModule from './../../vendor/lib/dist/mod.js' будущее.
  2. Помимо самого пути, указание имени файла также связывает вас. Что-то вроде этого кажется невинным:

    import $ from 'vendor/jquery.js'

    Но как насчет того дня, когда я хочу использовать Zepto вместо jQuery ? Я нашел абстракцию, особенно вокруг библиотек поставщиков, очень полезную при работе с большими кодовыми базами, упрямыми разработчиками и постоянно меняющейся экосистемой JavaScript. Возможно, мне захочется импортировать React в качестве моей библиотеки компонентов сегодня, но как насчет завтра? Более того, что, если я собираюсь использовать тот же модуль как на клиенте, так и на сервере, но мне нужны разные версии зависимой библиотеки?

Я настаиваю на надежной (но четкой и последовательной) абстракции в моих командах. Часто время абстракция принимала форму своего рода пространств имен. Я немного фантазирую об этом:

//BAD: Bakes React into my component modules
import ComponentLib from './React.js';

//GOOD: Leaves me free to use any React-like library
import ComponentLib from 'vendor.lib.component';

Где vendor.lib.component , vendor.lib.component на Java, был зарегистрирован где-то ранее.

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

Подобные вопросы привели к предложению библиотеки, которая использует спецификацию системы , например SystemJS . Затем вы можете использовать что-то вроде jspm, чтобы ввести карту модуля, чтобы получить абстракцию. Но как только я это сделаю, я пишу все свои модули по-разному:

System.import('a', function(A){
  //use 'A'
});

Это вдруг будущее? Если да, почему бы мне просто не использовать AMD? Зачем даже беспокоиться с модулями ES2015 и запуском транспиляторов, если я только вернусь к использованию асинхронного API-интерфейса загрузчика?

Больше взгляда, я не вижу большого упоминания о том, как использовать стандарт API загрузчика модулей в спецификации ES2017 .

( EDIT: Вопрос пересмотрен для соответствия стандартам ответа, не основанного на мнениях )

Учитывая все вышеизложенное, я спрашиваю сообщество - как написать модуль JavaScript, который (i) соблюдает стандарт ES2015, (ii) не ссылается на зависимый модуль по его имени файла или пути, и (iii) не полагается на обширные промежуточные инструменты / конфигурацию, которые сделали бы использование модуля с несколькими командами непомерно высокими.

-

Примечание 1 Как отмечает @zeroflagL в комментариях, спецификация явно не указывает, что модуль должен быть указан как путь, просто строка (см. ModuleSpecifier - http://www.ecma-international.org/ecma-262/ 6.0 / # таблица-41 ). Тем не менее, существует также четкая инструкция для учета циклических ссылок, что подразумевает какой-то статический анализ ( http://www.ecma-international.org/ecma-262/6.0/#sec-imports ), причем пути к файлам, казалось бы, справочный контекст выбора к этому моменту. Поэтому мы не можем обвинять спецификацию в том, что она здесь жесткая, а наоборот. В то же время бремя может быть на всех остальных для разработки более надежных реализаций import / ModuleSpecifier, которые приводят к вторичному стандарту.


Для меня это, по-видимому, одна из самых больших нерешенных проблем сообщества JS. В отношении управления зависимостями и зависимостей (по крайней мере, насколько мне известно) не существует оптимальной практики.

В этой ветке есть долгая дискуссия: нужна ли мне инъекция зависимостей в NodeJS или как бороться с ней? , но большинство решений, похоже, работают только для конкретных случаев и требуют изменения способа записи модулей каким-то образом. И самым шокирующим является то, что многие ответы утверждают, что вам даже не нужен DI.

Мое собственное решение проблемы - это минимальная среда DI , которая позволяет вам определять модули один раз, и она подключит их для вас с надлежащими зависимостями.


Если вы хотите следовать передовым методам, следуйте инструкциям AirBnb JavaScript styleguide. По-моему, лучший и самый полный стиль JavaScript

https://github.com/airbnb/javascript#classes--constructors

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

Это выглядит плохо для повторного использования модулей: import myModule from './../../vendor/lib/dist/mod.js'

Публикуйте свой модуль на NPM (который также может быть приватным или самостоятельно размещенным NPM) и импортируйте, как этот import myModule from 'my-module';

В конце концов, установите NODE_PATH в качестве корневой папки и обратитесь к модулям относительно от корня.

В пакете.json

'start': 'NODE_PATH=. node index.js'

// in Windows
'start': 'NODE_PATH=. && node index.js'

Теперь импортируйте вот так:

import myModule from 'vendor/lib/dist/mod.js'

переменные

var не является частью ES6. Использование:

  • constant - когда значение переменной не изменится, также объекты и импорт. Даже если параметры объекта изменяются, он по-прежнему является константой.

  • let - когда изменяется значение переменной, т. е. for(let = i; i < 100; i++)

  • Из моего собственного опыта всегда устанавливайте const как значение по умолчанию, и только изменение let если ESLint жалуется (кстати, используйте ESLint http://eslint.org/ )

Классы

Теперь есть правильный способ определения классов в JavaScript

class B {
  constructor() {
  }
  doSomething() {
  }
}

Ваш пример обновлен:

import A from './a';

Class B {
  constructor() {
  }
  doSomething() {
  }
};

export default B;

Если вы хотите расширить A:

import A from './a';

Class B extends A{
  constructor(argumentA, argumentB) {
    super(argumentA, argumentB);
    this.paramA = argumentA;
  }
};

export default B;

Советы

  • Используйте Webpack с NPM как инструмент сборки. Не используйте Gulp или Grunt
  • Используйте Babel для перевода вашего кода (загрузчика JSX может быть недостаточно)
  • Научитесь вообще не использовать jQuery, но вместо этого выбирайте правильные полисы и инструменты для работы, которые вам нужно делать из NPM
  • Есть тонны хорошо написанных плановых репозиториев на github, поэтому украсть из лучших. Вот некоторые из них, которые я использую.
    • https://github.com/davezuko/react-redux-starter-kit
    • https://github.com/kriasoft/react-starter-kit
    • как вы можете видеть, я большой поклонник React. Также полный рабочий день профессиональный пользователь уже более двух лет.
    • Чтобы найти хороший пример кода, поиск по github, т.е. «реагировать» или «узел», затем сортировать результаты по звездам)

Мой ответ в основном таков:

Образец / библиотека, которую вы просили, это AirBnb JavaScript styleguide и забыть о jQuery





ecmascript-6