Что угловой компилятор "компилирует"?
Меня спросили об этом сегодня, и я не смог дать правильный ответ.
Машинопись переносится в JS. Затем происходит встряхивание дерева, "меньше" (необязательно) и что еще в процессе развертывания. Но ничего подобного (afaik) не имеет ничего общего с "компиляцией". Все упаковано и оптимизировано, но на самом деле не скомпилировано, верно?
Есть даже опережающий компилятор, который действительно делает заметную работу. Что мне не хватает?
Сам Javascript все еще интерпретируется, верно?
5 ответов
Вы предполагаете, что компиляция означает получение исходного кода и создание машинного кода, низкоуровневых кодов и т. Д. Но на самом деле компиляция означает просто получение одного исходного кода и превращение его в другой. Поэтому кажется разумным сказать, что использование Typescript и создание JavaScript - это форма компиляции. Это не отличается от того, что (например) делает C# при компиляции в язык IL.
Тем не менее, я бы сказал, что лучшее слово для этого - Transpiling. Я бы предположил, что компилятор Typescript лучше описать как Transpiler.
Разница невелика, и транспортер можно рассматривать как тип компилятора; но (чистый) скомпилированный язык (обычно) превращает язык высокого уровня в язык низкого (эр) уровня (ближе к машинному коду), как пример C#. Транспортер превращает язык высокого уровня в язык аналогичного уровня (абстракции) (также высокого уровня).*
Результат скомпилированного кода, как правило, не является языком, который вы написали бы сами. Результатом транспилятора является другой язык высокого уровня. Теоретически, вы могли бы написать IL (в качестве примера), но он действительно предназначен для создания компилятором, и для этого нет инструментов или поддержки, вы создаете IL только путем компиляции C#/vb.net. Принимая во внимание, что Javascript - это удобный (и используемый) язык программирования сам по себе.
* Много предостережений, так как определения этих слов и их использование довольно расплывчаты
Вы, кажется, задаете три вопроса в одном:
- В чем разница между компилятором и транспилером?
- Реализуют ли Angular и TypeScript компиляторы или транспортеры?
- Есть ли отдельный угловой компилятор? Что это компилирует?
В чем разница между компилятором и транспилером?
@ JörgWMittag дал очень хороший ответ на этот вопрос.
Реализуют ли Angular и TypeScript компиляторы или транспортеры?
И TS, и Angular реализуют реальные компиляторы. Они следуют тем же этапам лексического анализа, синтаксического анализа, семантического анализа и генерации кода, что и компиляторы C/C++, которые создают ассемблерный код (за исключением, вероятно, для оптимизации). Вы можете видеть, что класс / папка называются "compiler" как в Angular, так и в TS.
Угловой компилятор не имеет никакого отношения к компилятору TypeScript. Это очень разные компиляторы.
Есть ли отдельный угловой компилятор? Что это компилирует?
Angular имеет два компилятора:
- Посмотреть компилятор
- Модульный компилятор
Задача компилятора представления состоит в том, чтобы преобразовать шаблон, указанный для шаблона компонента, во внутреннее представление компонента, которое представляет собой фабрику представления, которая затем используется для создания экземпляра представления.
Помимо преобразования шаблона, компилятор представления также компилирует различную информацию метаданных в виде декораторов, таких как @HostBinding
, @ViewChild
и т.п.
Предположим, вы определили компонент и его шаблон следующим образом:
@Component({
selector: 'a-comp',
template: '<span>A Component</span>'
})
class AComponent {}
Используя эти данные, компилятор генерирует следующую слегка упрощенную фабрику компонентов:
function View_AComponent {
return jit_viewDef1(0,[
elementDef2(0,null,null,1,'span',...),
jit_textDef3(null,['My name is ',...])
]
Он описывает структуру представления компонента и используется при создании экземпляра компонента. Первый узел - это определение элемента, а второй - определение текста. Вы можете видеть, что каждый узел получает информацию, в которой он нуждается при создании экземпляра через список параметров. Задача компилятора - разрешить все необходимые зависимости и предоставить их во время выполнения.
Я настоятельно рекомендую прочитать эти статьи:
- Вот что вам нужно знать о динамических компонентах в Angular
- Вот почему вы не найдете компоненты внутри Angular
Также см. Ответ на вопрос "В чем разница между Angular AOT и JIT-компилятором?".
Задача компилятора модуля - создать фабрику модулей, которая в основном содержит объединенные определения поставщиков.
Для получения дополнительной информации читайте:
Машинопись происходит в JS. Затем происходит встряхивание дерева, "меньше" (необязательно) и что еще в процессе развертывания. Но ничего подобного (afaik) не имеет ничего общего с "компиляцией". Все упаковано и оптимизировано, но на самом деле не скомпилировано, верно?
Компиляция означает преобразование программы, написанной на языке A, в семантически эквивалентную программу, написанную на языке B, так что оценка скомпилированной программы в соответствии с правилами языка B (например, интерпретация ее с помощью интерпретатора для B) дает тот же результат и имеет те же побочные эффекты, что и при оценке исходной программы в соответствии с правилами языка A (например, интерпретация ее с помощью переводчика для A).
Компиляция просто означает перевод программы с языка A на язык B. Это все, что это значит. (Также обратите внимание, что вполне возможно, что A и B будут на одном языке.)
В некоторых случаях у нас есть более специализированные имена для определенных типов компиляторов, в зависимости от того, что такое A и B и что делает компилятор:
- если A воспринимается как ассемблер, а B воспринимается как машинный язык, то мы называем его ассемблером,
- если A воспринимается как машинный язык, а B воспринимается как язык ассемблера, то мы называем его дизассемблером,
- если A воспринимается как более низкий уровень, чем B, то мы называем это декомпилятором,
- если A и B - один и тот же язык, и результирующая программа в некотором роде быстрее или легче, тогда мы называем это оптимизатором,
- если A и B - одни и те же языки, а результирующая программа меньше, то мы называем это минификатором,
- если A и B - одни и те же языки, и результирующая программа менее читаема, то мы называем ее обфускатором,
- если А и В воспринимаются примерно на одном уровне абстракции, то мы называем это транспортером, и
- если A и B воспринимаются как находящиеся примерно на одном уровне абстракции, и результирующая программа сохраняет форматирование, комментарии и намерения программиста, так что можно сохранить результирующую программу таким же образом, как и исходная программа, тогда мы вызываем это инструмент реинжиниринга.
Также обратите внимание, что более старые источники могут использовать термины "перевод" и "переводчик" вместо "компиляция" и "компилятор". Например, C говорит о "единицах перевода".
Вы также можете наткнуться на термин "языковой процессор". Это может означать либо компилятор, интерпретатор, либо компиляторы и интерпретаторы в зависимости от определения.
Сам Javascript все еще интерпретируется, верно?
JavaScript это язык. Языки представляют собой набор логических правил и ограничений. Языки не интерпретируются и не компилируются. Языки просто есть.
Компиляция и интерпретация являются чертами компилятора или интерпретатора (дух!). Любой язык может быть реализован с помощью компилятора, и каждый язык может быть реализован с помощью интерпретатора. Многие языки имеют как компиляторы, так и интерпретаторы. Многие современные высокопроизводительные механизмы исполнения имеют как минимум один компилятор, так и хотя бы один интерпретатор.
Эти два термина принадлежат разным слоям абстракции. Если бы английский был типизированным языком, "интерпретированный язык" был бы ошибкой типа.
Также обратите внимание, что в некоторых языках нет ни интерпретатора, ни компилятора. Есть языки, которые вообще не имеют реализации. Тем не менее, они являются языками, и вы можете писать программы на них. Вы просто не можете запустить их.
Также обратите внимание, что в какой-то момент все интерпретируется: если вы хотите что-то выполнить, вы должны это интерпретировать. Компиляция просто переводит код с одного языка на другой. Это не работает. Интерпретация запускает это. (Иногда, когда интерпретатор реализован аппаратно, мы называем его "ЦП", но это все же интерпретатор.)
Пример: каждая существующая в настоящее время основная реализация JavaScript имеет компилятор.
V8 начинался как чистый компилятор: он компилировал JavaScript прямо в умеренно оптимизированный машинный код. Позже был добавлен второй компилятор. Теперь есть два компилятора: легкий компилятор, который производит умеренно оптимизированный код, но сам компилятор очень быстрый и использует мало оперативной памяти. Этот компилятор также внедряет профилирующий код в скомпилированный код. Второй компилятор - это более тяжелый, более медленный и более дорогой компилятор, который, однако, производит гораздо более жесткий и гораздо более быстрый код. Он также использует результаты кода профилирования, введенного первым компилятором, для принятия решений по динамической оптимизации. Кроме того, решение о том, какой код перекомпилировать с использованием второго компилятора, принимается на основе этой информации профилирования. Обратите внимание, что ни в коем случае не привлекается переводчик. V8 никогда не интерпретирует, он всегда компилируется. Он даже не содержит переводчика. (На самом деле, я думаю, что в настоящее время это так, я описываю первые две итерации.)
SpiderMonkey компилирует JavaScript в байт-код SpiderMonkey, который затем интерпретирует. Интерпретатор также профилирует код, а затем код, который выполняется чаще всего, компилируется компилятором в машинный код. Итак, SpiderMonkey содержит два компилятора: один от JavaScript до байт-кода SpiderMonkey, а другой от байт-кода SpiderMonkey до машинного кода.
Почти все механизмы исполнения JavaScript (за исключением V8) следуют этой модели компилятора AOT, который компилирует JavaScript в байт-код, и механизма смешанного режима, который переключается между интерпретацией и компиляцией этого байт-кода.
Вы написали в комментарии:
Я действительно думал, что машинный код где-то участвует.
Что означает "машинный код"?
Какой машинный язык одного человека является промежуточным языком другого человека и наоборот? Например, существуют процессоры, которые могут выполнять собственный байт-код JVM, на этом процессоре байт-код JVM является машинным кодом. И есть интерпретаторы для машинного кода x86, при запуске которого машинный код x86 интерпретируется байт-кодом.
Существует интерпретатор x86 под названием JPC, написанный на Java. Если я запускаю машинный код x86 на JPC, работающем на собственном процессоре JVM... какой это байт-код, а какой родной код? Если я скомпилирую машинный код x86 в JavaScript (да, есть инструменты, которые могут это сделать) и запустлю его в браузере на моем телефоне (с процессором ARM), какой это байт-код, а какой - машинный код? Что если программа, которую я компилирую, является эмулятором SPARC, и я использую его для запуска кода SPARC?
Обратите внимание, что каждый язык вызывает абстрактную машину и является машинным языком для этой машины. Итак, каждый язык (включая языки очень высокого уровня) является машинным кодом. Также вы можете написать переводчика для каждого языка. Таким образом, каждый язык (включая машинный код x86) не является родным.
Получение кода, который вы написали для запуска в браузере, включает в себя две вещи:
1) Транспортировка Typescript в JavaScript. Это своего рода решенная проблема. Я думаю, что они просто используют веб-пакет.
2) Компиляция угловых абстракций в JavaScript. Я имею в виду такие вещи, как компоненты, каналы, директивы, шаблоны и т. Д. Это то, над чем работает основная команда Angular.
Если вам действительно интересен второй бит, угловой компилятор, автор часового компилятора Тобиас Бош (Tobias Bosch) объяснит Angular Compiler на AngularConnect 2016.
Я думаю, что здесь происходит некоторая путаница между переносом и компиляцией. Это не имеет значения и является вопросом личного вкуса, они оба просто трансформируются между представлениями кода. Но определение, которое я лично использую, заключается в том, что перенос происходит между двумя разными языками на одинаковом уровне абстракции (например, от машинописного до javascript), тогда как компиляция требует понижения уровня абстракции. Я думаю, от шаблонов, компонентов, каналов, директив и т. Д. До простого javascript - это шаг вниз по лестнице абстракции, и именно поэтому он называется компилятором.
Угловой компилятор
Одно из самых важных изменений от Angular 4 к 5 - компилятор был переписан быстрее и тщательнее. В прошлом приложения Angular использовали то, что мы называем JIT-компиляцией, когда приложение компилировалось во время выполнения в браузере перед запуском. Обновления компилятора в Angular 5 продвинули переход к AOT, что сделало приложение быстрее, поскольку оно выполняет меньше компиляции при запуске приложения. AOT включается по умолчанию в любой производственной сборке, начиная с версии 1.5 Angular CLI.
Допустим, мы хотим создать приложение для развертывания и выполнить следующую команду:
ng build --prod
Происходит несколько вещей: производственная версия, минификация, объединяет ресурсы, хеширование имени файла, встряхивание дерева, AOT ... (мы можем включить / отключить это с помощью флагов, например, aot=false). Короче говоря, флаг prod создает оптимизированный пакет приложения, выполняя компиляцию AOT с использованием ngc (компилятор Angular) для создания оптимизированного кода, готового для браузера (да, он предварительно компилирует шаблоны).
Компилятор TypeScript
Компилятор TypeScript, tsc, отвечает за компиляцию файлов TypeScript. Именно компилятор отвечает за реализацию функций TypeScript, таких как статические типы, и в результате получается чистый JavaScript, из которого удалены ключевые слова и выражения TypeScript.
Компилятор TypeScript имеет две основные функции: это транспилятор и средство проверки типов. Компилятор преобразует TypeScript в JavaScript. Он выполняет следующие преобразования вашего исходного кода:
- Удалите все аннотации типов.
- Компилировать новые функции JavaScript для старых версий JavaScript.
- Скомпилируйте функции TypeScript, которые не являются стандартным JavaScript.
Вызывая его, компилятор ищет конфигурации, загруженные в tsconfig.json (подробный список всех параметров компилятора вместе со значениями по умолчанию можно найти здесь).
Во многих отношениях компилятор TypeScript работает как любой компилятор. Но есть одно отличие, которое может уловить неосторожных: по умолчанию компилятор продолжает выдавать код JavaScript, даже если он обнаруживает ошибку. К счастью, это поведение можно отключить, установивnoEmitOnError
для параметра конфигурации значение true в файле tsconfig.json.
Примечание: tsc и ngc имеют разные цели, и речь не идет о выборе одного из них над другим. Этот ответ может быть интересен.
Этот ответ был составлен на основе материалов следующих книг
Хлоя, М. (2018). "Проекты Angular 5: научитесь создавать одностраничные веб-приложения, используя более 70 проектов".
Дьюи, Б., Гроссниклаус, К., Япикс, П. (2017). "Создание веб-приложений с помощью Visual Studio 2017: использование.NET Core и современных платформ JavaScript".
Фриман, А. (2019). "Основной TypeScript: от новичка до профессионала".
Гия, П. (2018). "Микросервисы TypeScript".
Искандар А., Чивукулу С. (2019). "Веб-разработка с использованием Angular и Bootstrap - третье издание".
Хеннесси, К., Арора, К. (2018). "Угловой 6 на примере".
Янсен, Р., Вольф, И., Ване, В. (2016). "TypeScript: современная разработка на JavaScript".
Мохаммед, З. (2019). "Угловые проекты".
Сешадри, С. (2018). "Угловой: Вверх и работает".
Уилкен, Дж. (2018). "Угловой в действии".
Для получения более подробной информации следуйте: https://en.wikipedia.org/wiki/Angular_(web_framework)
Straight answer to your question is:
У angular нет компилятора. Потому что это не язык.
Но у typcript есть компилятор, на котором написана языковая угловая библиотека /FrameWork.
Так как у него нет компилятора, он не может ничего скомпилировать.
1.) " Angular " (версии 2.x и выше) - это библиотека /FrameWork, написанная с использованием языка, который называется typcript.
- Так что он использует TypeScript Compiler.
2.) Напротив, angularjs (версии 1.x) - это библиотека /FrameWork, написанная на языке, называемом сценарием Java.
- Так что он использует интерпретатор JavaScript.
почему компилятор:
Поскольку angular написан с использованием машинописного текста, он неизвестен браузеру (это реальная платформа, на которой функциональный код выполняется для веб-приложений).
Таким образом, с помощью компилятора машинописи угловые компоненты преобразуются в понятные браузеру компоненты Java-скриптов.
СОВЕТЫ ДЛЯ ВСЕХ: Всегда всегда НАЧИНАЙТЕ ответы (и исследования) с ОПРЕДЕЛЕНИЙ! СЛОВАРЬ MERRIAM-WEBSTER... Скомпилировать: глагол компьютеров: "преобразовать (инструкции по компьютерному программированию) в форму, которую компьютер сможет понять и использовать"
WIKIPEDIA... Компилятор - это компьютерная программа, которая преобразует компьютерный код, написанный на одном языке программирования (исходный язык), в другой язык программирования (целевой язык). Компиляторы - это тип переводчика, который поддерживает цифровые устройства, прежде всего компьютеры. Компилятор имен в основном используется для программ, которые переводят исходный код с языка программирования высокого уровня на язык более низкого уровня (например, язык ассемблера, объектный код или машинный код) для создания исполняемой программы.[1]
ОБСУЖДЕНИЕ. Словарь Вебстера здесь следует считать высшим авторитетом, но его определение разочаровывающе расплывчато.
Википедия действительно является фактическим авторитетным источником. Если в этом случае мы рассматриваем его объяснение как вышестоящий орган, то он (как обычно) старается предложить действительно полезную информацию, в частности следующее:
- Компиляция в самом строгом смысле означала "перевод программного кода с языка, который НЕ был непосредственно исполняется компьютером, в код, который непосредственно исполнялся компьютером".
- ЕСЛИ мы принимаем вышеупомянутое как ОБЩЕЕ определение "компиляции"... ЕСЛИ все, что происходит в Angular, это "перевод" Typescript в Javascript... ЕСЛИ для кода Javascript все еще требуется "Интерпретация" в байт-код... Если байт-код затем интерпретируется node.js в код, исполняемый компьютером... ТО, что делает Angular, НЕ "СОБИРАЕТСЯ" в прямом смысле. Период.
ЭТО СКАЗАЛ...
- ЕСЛИ мы ослабляем наше определение "компиляции", чтобы просто означать "перевод программного кода с языка более высокого уровня на язык более низкого уровня"... Если мы принимаем, что Typescript является (во многих отношениях) языком "более высокого уровня" чем Javascript... ТО, что делает Angular (перевод Typescript в Javascript) "компилируется"...
ЭТО СКАЗАЛ...
- Если мы введем несколько новых типов компиляции (согласно Википедии):
- Компиляция: перевод кода с языка более высокого уровня на язык более низкого уровня;
- Транспилирование: перевод кода между по существу "эквивалентными" языками; а также
- Декомпиляция: перевод кода с языка более низкого уровня на язык более высокого уровня; ПОТОМ, будет ли Angular "компилировать" или "переносить", зависит от того, принимаете ли вы утверждение, что Typescript (даже немного) является языком "более высокого" уровня, чем Javascript.
Мне? а. Я предпочитаю "рабочее определение" компиляции как "перевод с высокого на низкий"; (оно более обобщенно и оставляет место для эволюции определения) б. Я также действительно считаю Typescript языком, возможно, "более высокого уровня", чем Javascript; SO c. Я в порядке с Angular, утверждающим, что он "компилируется"
АЛЬТЕРНАТИВА НЕОБХОДИМА: если мы требуем, чтобы "компиляция" означала "перевод в" исполняемый "код"; ЕСЛИ мы принимаем, что Typescript "выше", чем Javascript; ТОГДА Angular НЕ "компилирует":-| но ТАКЖЕ Angular НЕ даже "переносится":-(! В действительности мы НЕ МОЖЕМ ДАЖЕ ОПИСАТЬ ТОЛЬКО ЧТО Angular ДЕЛАЕТ доступный словарь!
Поэтому я "обобщаю" (читай "расслабляюсь") мое определение "компилировать", чтобы оно означало просто "выше-ниже" вместо "выше-к-машине", и теперь мой доступный словарь МОЖЕТ описать, что делает Angular - это IS "компилирует"
Если целью этого обсуждения является УЛУЧШЕНИЕ ПОНИМАНИЯ, то я надеюсь, что мое небольшое предложение будет полезно для некоторых.
Ура -марк в Северной Авроре Ил