Вот более конкретный пример.
Я работаю над проектом с 60 файлами. У нас есть 2 разных режима работы.
Загрузите составную версию, 1 большой файл. (Производство)
Загрузить все 60 файлов (разработка)
Мы используем загрузчик, поэтому у нас есть только один скрипт на веб-странице.
<script src="loader.js"></script>
По умолчанию используется режим № 1 (загрузка одного большого объединенного файла). Для запуска в режиме #2 (отдельные файлы) мы устанавливаем какой-то флаг. Это может быть что угодно. Ключ в строке запроса. В этом примере мы просто делаем это
<script>useDebugVersion = true;</script>
<script src="loader.js"></script>
loader.js выглядит примерно так
if (useDebugVersion) {
injectScript("app.js");
injectScript("somelib.js");
injectScript("someotherlib.js");
injectScript("anotherlib.js");
... repeat for 60 files ...
} else {
injectScript("large-concatinated.js");
}
Сценарий сборки - это просто файл .sh, который выглядит так
cat > large-concantinated.js app.js somelib.js someotherlib.js anotherlib.js
и т.д...
Если добавляется новый файл, мы, вероятно, будем использовать режим № 2, так как мы занимаемся разработкой, нам нужно добавить строку injectScript("somenewfile.js")
в loader.js.
Затем позже для производства мы также должны добавить somenewfile.js в наш скрипт сборки. Шаг, который мы часто забываем, а затем получаем сообщения об ошибках.
При переходе на AMD нам не нужно редактировать 2 файла. Проблема синхронизации loader.js и скрипта сборки исчезает. Используя r.js
или webpack
, он может просто прочитать код для сборки large-concantinated.js
.
Он также может иметь дело с зависимостями, например, у нас было загружено 2 файла lib1.js и lib2.js следующим образом.
injectScript("lib1.js");
injectScript("lib2.js");
lib2 нужна lib1. Внутри него есть код, который делает что-то вроде
lib1Api.installPlugin(...);
Но поскольку внедренные скрипты загружаются асинхронно, нет гарантии, что они загрузятся в правильном порядке. Эти 2 скрипта не являются скриптами AMD, но с помощью require.js мы можем указать их зависимости.
require.config({
paths: {
lib1: './path/to/lib1',
lib2: './path/to/lib2',
},
shim: {
lib1: {
"exports": 'lib1Api',
},
lib2: {
"deps": ["lib1"],
},
}
});
Я наш модуль, который использует lib1, мы делаем это
define(['lib1'], function(lib1Api) {
lib1Api.doSomething(...);
});
Теперь require.js будет внедрять скрипты для нас и не будет внедрять lib2 до тех пор, пока не будет загружена lib1, поскольку мы сказали, что lib2 зависит от lib1. Он также не запустит наш модуль, использующий lib1, пока не загрузятся и lib2, и lib1.
Это делает разработку приятной (без этапа сборки, не нужно беспокоиться о порядке загрузки) и делает производство приятным (нет необходимости обновлять скрипт сборки для каждого добавленного скрипта).
В качестве дополнительного бонуса мы можем использовать плагин babel из webpack, чтобы запускать babel поверх кода для старых браузеров, и опять же нам не нужно поддерживать этот скрипт сборки.
Обратите внимание, что если бы Chrome (наш любимый браузер) начал поддерживать import
по-настоящему, мы бы, вероятно, переключились на него для разработки, но на самом деле это ничего не изменило бы. Мы по-прежнему могли бы использовать webpack для создания составного файла, и мы могли бы использовать его для запуска babel над кодом для всех браузеров.
Все это достигается за счет отказа от тегов script и использования AMD.
person
gman
schedule
06.01.2017