Sencha Ext JS: за пределами ES5
Использование современного синтаксиса ECMAScript с проектами Sencha Ext JS
Sencha Ext JS поставляется с инструментом сборки с закрытым исходным кодом, в который входит Closure Compiler; в некоторых случаях это не позволяет разработчикам использовать современный синтаксис ECMAScript. В этой статье представлен @coon-js/delorean, инструмент, который решает эту проблему с помощью дополнительного слоя транспиляции.
Одной из причин разочарования при работе с Ext JS является тот факт, что современный синтаксис JavaScript нельзя использовать с этой инфраструктурой: как только Sencha CMD создает пакет или приложение, код, который известно, что он работает в разработке, или тесты не компилируются для производства, или, что еще хуже, он полностью ломается во время производства.
Вот несколько примеров, которые, как известно, ломают сборку с Sencha CMD:
Оператор нулевого объединения:
const foo = null ?? ‘default string’;
Синтаксис деструктурирования присваивания с аргументами функции:
const fn = ([x, y, z]) => ({x, y, z});
Необязательный оператор цепочки:
const adventurer = { name: 'Alice', cat: { name: 'Dinah' } }; const dogName = adventurer.dog?.name;
Причина этого в том, что Sencha CMD — это проприетарный инструмент, который поставляется со встроенным компилятором закрытия; то, как он интегрирован, не позволяет разработчикам точно настраивать процессы сборки. Очевидно, что компилятор Closure требует обновлений для работы с текущими стандартами ECMAScript. Есть несколько параметров конфигурации для пакетов, которые обеспечивают более щадящий (читай: совместимый) синтаксический анализ и транспилирование исходного кода. Однако есть код, который, как известно, дает сбой во время компиляции, даже если код синтаксически правильный.
(Обратитесь к этому списку, чтобы получить представление о том, что работает с Closure Compiler.)
Также обратите внимание, что последняя доступная версия Closure Compiler не обязательно поставляется с последней доступной версией Sencha CMD: v7.6.0.87 Sencha CMD поставляется с v20220301.
@sencha\cmd> dir /s/b | findstr .*closure.*$ @sencha\cmd\dist\lib\closure-compiler-externs-v20220301.jar @sencha\cmd\dist\lib\closure-compiler-v20220301.jar
К сожалению, Sencha не предоставляет официального руководства по независимому обновлению компилятора Closure.
Когда дела идут в самоволку
Вот пример, который показывает, как производственный код проекта Ext JS ломается при использовании современного ECMAScript. Рассмотрим следующие строки как часть исходного кода разработки:
const fn = ([a, b, c]) => ({a, b, c});
Эта стрелочная функция
- использует синтаксис деструктурирующего присваивания для распаковки первых трех записей аргумента массива
- создает объект из записей, используя обозначение сокращенных имен свойств
- возвращает этот объект
Пусть код будет частью пакета Sencha Ext JS, который можно собрать с помощью команды:
npx @sencha/cmd package build
Версия, используемая с Sencha CMD:
npx @sencha/cmd which Sencha Cmd v7.6.0.87
И конфигурация из раздела sencha
package.json:
"output": { "base": "${package.dir}/build" }, "compressor": { "type": "closure", "polyfills": "none" },
Компиляция не удалась, так как уровень вывода по умолчанию установлен на ES5; это старая спецификация ES, но совместимая с широким спектром браузеров:
Конфигурацию можно настроить таким образом, чтобы можно было указать версию ES, используемую в проекте: Зная, что NEXT — это уровень для последних поддерживаемых функций, конфигурация изменяется на:
"output": { "base": "${package.dir}/build", "js": { "version": "NEXT" } }, "language": { "js": { "input": "NEXT", "output": "NEXT" } }, "compressor": { "type": "closure", "polyfills": "none" },
Вывод на консоли показывает, что команда NEXT понята, но при компиляции все еще происходит сбой: файлы сборки остаются пустыми.
Видимо, где-то что-то сломалось.
Кажется, что language.js.input
вызывает проблемы. Согласно официальной документации Sencha, инструмент поддерживает следующие языковые уровни:
ES3 : ECMAScript 3 language level ES5 : ECMAScript 5 language level ES6 : ECMAScript 6 language level (2015) ES7 : ECMAScript 7 language level (2016) ES8 : ECMAScript 8 language level (2017) NEXT : ECMAScript Next (or ES.Next) language level
тогда как Closure Compiler поддерживает следующие спецификации с language_in
:
ECMASCRIPT3 ECMASCRIPT5 ECMASCRIPT5_STRICT ECMASCRIPT_2015 ECMASCRIPT_2016 ECMASCRIPT_2017 ECMASCRIPT_2018 ECMASCRIPT_2019 ECMASCRIPT_2020 ECMASCRIPT_2021 STABLE ECMASCRIPT_NEXT (latest features supported) (default: STABLE)
К сожалению, попытка установить язык на любое из значений, поддерживаемых непосредственно компилятором Closure (или его вариациями, такими как ECMASCRIPT_2021, ES10…), приводит к следующему: сообщение об ошибке:
ES8 кажется самым большим общим знаменателем для Sencha CMD и компилятора Closure. Работает следующая конфигурация — процесс сборки не прерывается на полпути, и транспилированный JavaScript оказывается в исходных файлах:
"output": { "base": "${package.dir}/build", "js": { "version": "ES8" } }, "language": { "js": { "input": "ES8", "output": "ES8" } }, "compressor": { "type": "closure", "polyfills": "none" }
Однако загрузка сборки в рабочей среде завершается сбоем.
Вот исходный код JavaScript для справки:
const fn = ([a, b, c]) => ({a, b, c});
… и исходный код JavaScript, который заканчивается кодом отладки (например, build/project-debug.js
):
const fn = [a,b,c] => ({ a, b, c });
… и это код, созданный для сжатого JavaScript (например, build/project.js
):
const c=()=>({a,b,c});
Не нужно много времени, чтобы понять, почему код дает сбой: он синтаксически неверен в отладочной сборке и функционально неверен в сжатой сборке.
Представляем @coon-js/delorean
Современные языковые функции могут поддерживаться с помощью дополнительной транспиляции: исходные коды разработки, использующие новейший синтаксис в соответствии со спецификациями ES, должны быть транспилированы заранее, передавая компилятору Closure версию JavaScript, которую он понимает, что приводит к правильным и пригодным для использования сборкам.
@coon-js/delorean — это инструмент npm, который обеспечивает дополнительный уровень транспиляции поверх Sencha CMD с помощью Babel.
Для выполнения этой работы delorean изменяет файл проекта пакета или приложения и перенаправляет исходные файлы на файлы, которые были обработаны и транспилированы Babel. Это позволяет использовать любую функцию языка JavaScript и дополнительные оптимизации, которые можно внедрить с помощью бесчисленного количества плагинов Babel.
Конфигурация delorean по умолчанию гарантирует, что Babel создаст код ES5:
delorean почти не влияет на фактический процесс сборки: он только обновляет существующие сопоставления в файле конфигурации, требуемом Sencha CMD; обычно они представляют собой каталоги, содержащие исходные файлы, относящиеся к проекту. Помимо очевидных каркасов перенесенного проекта, инфраструктура проекта остается нетронутой, что делает возможной почти бесшовную интеграцию в процесс разработки и существующие конвейеры сборки.
Изменения, внесенные в конфигурацию проекта, легко отследить:
"classpath": [ - "${package.dir}/src", - "${package.dir}/${toolkit.name}/src" + "${package.dir}/.deloreanbuild/src", + "${package.dir}/.deloreanbuild/${toolkit.name}/src" ], "overrides": [ - "${package.dir}/overrides", - "${package.dir}/${toolkit.name}/overrides" + "${package.dir}/.deloreanbuild/overrides", + "${package.dir}/.deloreanbuild/${toolkit.name}/overrides" ],
Во время разработки изменения, внесенные delorean, должны быть отменены, чтобы перезагрузка в реальном времени с sencha app watch
соответствующим webpack (являющимся частью проектов Ext JS, используемых с npm) по-прежнему работала — и конечно, чтобы браузер использовал исходники из файлов, редактируемых в данный момент разработчиком. (В противном случае среда разработки будет полагаться на транспилированные файлы, созданные ранее delorean.)
Отменить изменения довольно легко, так как простой вызов
npx delorean -r
удаляет любую ссылку на папку .deloreanbuild
из файла конфигурации проекта:
Интеграция CI/CD
npx delorean -p
и npx delorean -r
легко интегрируются с конвейерами CI/CD, обычно используемыми в проектах Sencha Ext JS.
Вы можете автоматизировать транспиляцию, настроив либо build.xml
пакета или приложения, либо добавив дополнительные scripts
в package.json
.
стратегия build.xml
Этот xml-файл обычно доступен с любым пакетом или приложением Ext JS и предоставляет место для добавления параметров и хуков для инструмента Ant, используемого с Sencha CMD. Он позволяет настроить -before-build
/-after-build
целей (подробнее об этом можно прочитать здесь).
Вы можете использовать delorean, настроив цели с помощью:
<target name="-before-build"> <exec executable="cmd"> <arg line="/c npx delorean -p"/> </exec> </target> <target name="-after-build"> <exec executable="cmd"> <arg line="/c npx delorean -r"/> </exec> </target>
Это запустит npx delorean -p
до того, как Sencha CMD создаст проект (отсюда -before-build
), и отменит все изменения, относящиеся к проекту, после завершения сборки, вызвав npx delorean -r
(отсюда -after-build
).
Стратегия package.json
Если у вас уже есть скрипт сборки в package.json
, который вызывает Sencha CMD, оберните команду build
дополнительными вызовами delorean. Вот пример:
{ "scripts": [ "build": "npx delorean -p && npm run senchabuild && npx delorean -r", "senchabuild": "npm run clean && cross-env webpack --env.profile=desktop --env.environment=production --env.treeshake=yes --env.cmdopts=--uses" ] }
Дополнительные ресурсы
Репозиторий проекта можно найти по адресу https://github.com/coon-js/delorean. Будем очень признательны за отзывы о конфигурациях, интеграции CI/CD и отчеты о проблемах.
Официальная документация для delorean доступна по адресу https://www.conjoon.org/docs/api/misc/@coon-js/delorean, который также является домом для его проекта, поскольку он возник как часть экосистемы conjoon.
Ранее я писал о выпуске conjoon 1.0.
Соединять
Торстен Зуков-Хомберг| Гитхаб| Твиттер| Ютуб| Инстаграм
Заметки сообщества
В Sencha Discord Server пользователи отреагировали на эту статью и отметили, что было бы также здорово полностью пропустить Sencha CMD и использовать такие инструменты, как webpack или rollup. исключительно для строительных проектов. Я полностью согласен и думаю, что предоставление решения для объединения активов и источников с помощью этих инструментов может быть выполнено с управляемыми усилиями.
Значительные изменения
- 02 декабря 2022 г.: Небольшие исправления при подготовке к немецкому переводу.
- 30 ноября 2022 г.: обновлен рис. 2 с конфигурацией
externals
. - 23 ноября 2022 г.: обновлена формулировка, добавлены примечания сообщества.
- 21 ноября 2022 г .: опубликована первая часть.