При загрузке свежего приложения Angular 11 будет создан следующий файл tsconfig.json
:
{
"compileOnSave": false,
"compilerOptions": {
... // Options not relevant for this question.
"target": "es2015",
"module": "es2020",
"lib": [
"es2018",
"dom"
]
}
Он также генерирует файл polyfills.ts
только с включенным/раскомментированным zone.js
.
Мой вопрос: поскольку мы компилируем в es2015
, но используем определения типов es2018
(например, async iterables
, promise.finally
и т. д.), как это может быть безопасно, если не предоставляются связанные полифилы?
Почему Angular 11 CLI не использует es2015
для lib
?
Угловые полифиллы автоматически генерируются как polyfills-es5.js
. В этом файле находятся полифилы, которые необходимы для внутренней работы angular. Если ваш код использует функции, которые не являются частью того, что использует angular, вам нужно добавить это в файл polyfills.ts
.
Поскольку целью является es2015, typescript автоматически преобразует некоторые функции es2018, например, async
.
es2015
автоматически включается как библиотека, потому что это подмножество es2018
(я полагаю).
Примечание:
Если бы вы использовали es2018
вместо target
, angular выдал бы предупреждение при компиляции, потому что нативный async/await
не может быть захвачен zone.js. Это не проблема, если вы везде используете OnPush
@domin Это правильно, но если вы используете функции, которые есть в es2018, которые нельзя перенести с помощью машинописного текста в es2015 и которые не используются основной структурой angular, вам необходимо включить их в свой polyfills.ts
Я так не думаю. Если я использую функцию ES2018 Promise.prototype.finally
, мне не нужно включать какие-либо полифиллы, и мое приложение по-прежнему нормально работает в современных браузерах.
@domin что-то подобное нельзя передать машинописным текстом. async/await
можно. Современные браузеры поддерживают finally
, поэтому, очевидно, вам не нужно включать его в свои полифилы :) Попробуйте запустить его в IE11, и я уверен, что вам придется его добавить.
Разве Promise.finally
не является стандартным вызовом метода, как и любой другой, и поэтому может быть скомпилирован TS? Существует ли он во время выполнения — другой вопрос. Это работает в современном браузере, поддерживающем ES2018, но не в IE11, который требует полифилла, правильно!
@domin, потому что это стандартный метод, переноса не произойдет. Транспиляция происходит с языковыми функциями, такими как await/async
или необязательной цепочкой ?.
. Методы объекта никогда не транспилируются для определенной цели и должны быть добавлены в полифиллы, если ваше приложение должно работать в браузерах, которые его не поддерживают. Я думаю, это лучшее объяснение :D
Я думаю, что мы просто не согласны с термином «транспиляция». Если я пишу программу X исключительно в синтаксисе ES2015, она является действительной TS, поскольку TS (синтаксически) является надмножеством ES2015. Если я запускаю компилятор TS поверх X, я получаю X без изменений. Я бы все же сказал, что X был перенесен в X. ;)
Кстати: вы говорите, что невозможность исправления нативного async/await
с помощью zone.js
не является проблемой при использовании стратегии обнаружения изменений onpush
. Почему это так? Angular все еще нужно выяснить, изменились ли какие-либо входные ссылки. Однако когда он делает эту проверку?
@domin эти проверки выполняются в декораторе @Input
(я думаю, по крайней мере, я бы так сделал). Вход преобразуется в сеттер и геттер. И когда он установлен, компонент помечен как грязный
О, это имеет смысл! :) Большое спасибо за ваши ответы!
Спасибо за Ваш ответ. Я думаю, что я получил это сейчас! Angular на самом деле хотел бы настроить таргетинг на
es2018
, но не может из-за проблемы с захватомasync-await
. Таким образом, вместо этого он нацелен наes2015
, но по-прежнему хочет, чтобы программист использовал другие интересныеes2018
функции. Для этого он просто указываетes2018
какlib
, зная, что предполагаемая версия среды выполнения (например, браузер) будет поддерживать эти функции. Вы можете это подтвердить?