Что компилирует угловой компилятор?

Меня спросили об этом сегодня, и я не смог дать надлежащего ответа.

Typescript транспилируется в JS. Затем идет встряхивание дерева, "менее" (необязательно) и что еще в процессе создания развертывания. Но ничего подобного (афаик) не имеет ничего общего с «компиляцией». Все объединяется и сильно оптимизируется, но на самом деле не компилируется, верно?

Есть даже компилятор "впереди времени", который действительно делает заметную работу. Что мне не хватает?

Сам Javascript все еще интерпретируется, верно?


person codepleb    schedule 10.10.2017    source источник
comment
Я согласен с тем, что не совсем компилирую. По сути, это вопрос определения компиляции. Некоторые предпочитают использовать слово транспиляция для обозначения преобразования TypeScript в JavaScript. Но да, по сути, роль компилятора Typescript заключается просто в создании Javascript из Typescript.   -  person Pac0    schedule 10.10.2017
comment
Взгляните на Babel — это компилятор или транспайлер?   -  person Bergi    schedule 10.10.2017
comment
@Pac0 Возможно, я что-то здесь неправильно понимаю, но если TypeScript в JavaScript — это транспиляция, разве GCC не будет транспилером C в машинный код? Как бы вы определили разницу между транспилятором и компилятором?   -  person 11684    schedule 10.10.2017
comment
транспиляторы - это компиляторы   -  person user253751    schedule 10.10.2017
comment
См. Что имеют в виду люди. когда они говорят транспайлер? (и продолжение «Мои первые пятнадцать компиляторов») (от кого-то, кто работает над компилятором), в котором утверждается, что «компилятор» — хорошее слово для подобных вещей.   -  person ShreevatsaR    schedule 11.10.2017
comment
Сам Javascript все еще интерпретируется, верно? - больше нет, он компилируется в машинный код на лету движком V8   -  person Max Koretskyi    schedule 11.10.2017
comment
Кроме того, ужасная тряска дерева выражений просто означает устранение (или удаление) мертвого кода. Использование последнего позволит получить больше результатов в Google... а также намного понятнее.   -  person Synxis    schedule 11.10.2017
comment
@Synxis Я бы сказал, что встряхивание дерева специально нацелено на устранение импорта мертвых модулей, но вы правы, граница также нечеткая и может привести к тому же вреду, что и различие com/trans-piler.   -  person Bergi    schedule 11.10.2017


Ответы (5)


Вы предполагаете, что компиляция означает получение исходного кода и создание машинного кода, низкоуровневых кодов и т. д. Но на самом деле компиляция означает просто преобразование одного исходного кода в другой. Поэтому кажется разумным сказать, что использование Typescript и создание JavaScript — это форма компиляции. Это не отличается от того, что (например) делает С#, когда он скомпилирован в язык IL.

Тем не менее, я бы сказал, что для этого лучше использовать слово Транспиляция. Я бы предположил, что компилятор Typescript лучше описывается как Transpiler.

Разница тонкая, и транспилятор можно рассматривать как тип компилятора; но (чистый) скомпилированный язык (обычно) превращает язык высокого уровня в язык низкого уровня (более близкий к машинному коду), как пример C #. Транспилятор превращает язык высокого уровня в язык аналогичного уровня (абстракции) (также высокого уровня).*

Результатом скомпилированного кода обычно является язык, который вы не написали бы сами. Результатом работы транспилятора является еще один язык высокого уровня. Теоретически вы можете написать IL (в качестве примера), но на самом деле он предназначен для создания компилятором, и для этого нет инструментов или поддержки, вы создаете IL, компилируя только C#/vb.net. Принимая во внимание, что Javascript сам по себе является удобным (и используемым) языком программирования.

* Много предостережений, поскольку определения этих слов и их использование довольно расплывчаты

person Liam    schedule 10.10.2017
comment
Разве JavaScript не является строго более низким уровнем, чем TypeScript? - person Bergi; 10.10.2017
comment
Хотя все в этом ответе правильно и полезно, тем более что определение компиляции всегда вызывает путаницу, оно не отвечает на вопрос в заголовке. Этот ответ говорит только о TypeScript, а вопрос касается Angular. Разница огромна. Вполне возможно использовать Angular, даже не зная, что такое TS. Я удивлен, что этот ответ был принят. - person Pedro A; 11.10.2017
comment
Компилятор должен по существу понимать всю программу, чтобы сгенерировать другую программу (которая обычно делает то же самое, но на другом языке, включая машинный код). - person Thorbjørn Ravn Andersen; 11.10.2017
comment
Я только что прочитал это дважды и не смог найти ответ на вопрос здесь. Ответ чуть ниже. - person angularrocks.com; 11.10.2017
comment
Неявный вопрос, который задавал ОП, поэтому они приняли это, был «правильно ли называть компилятор Angular компилятором?» — и вот что отвечает этот ответ. Так что +1 от меня. См. также Что люди когда говорят транспайлер? и продолжение «Мои первые пятнадцать компиляторов». - person ShreevatsaR; 11.10.2017
comment
Транспиляция никогда не бывает полезным словом. Единственное, чего он достигает, - это приводить к неправильным представлениям, подобным тому, что в ОП. Избегайте любой ценой и относитесь к этим вещам правильно: как к компиляторам. - person Leushenko; 11.10.2017
comment
@ShreevatsaR Точно. Я не носитель языка, и то, что я думаю, не на 100% то, что я могу выразить в словах, особенно на другом языке. Но то, что здесь объяснил Лайам, было именно тем, что смутило меня. Жаль народ не согласен. Глядя на это сейчас, я вижу, как это немного сбивает с толку. - person codepleb; 11.10.2017

Кажется, вы задаете три вопроса в одном:

  • В чем разница между компилятором и транспилером?
  • Реализуют ли Angular и TypeScript компиляторы или транспиляторы?
  • Есть ли отдельный компилятор Angular? Что он компилирует?

В чем разница между компилятором и транспилером?

@JörgWMittag дал очень хороший ответ на этот вопрос.

Реализуют ли Angular и TypeScript компиляторы или транспиляторы?

И в TS, и в Angular реализованы настоящие компиляторы. Они проходят те же этапы лексического анализа, синтаксического анализа, семантического анализа и генерации кода, что и компиляторы C/C++, которые создают ассемблерный код (за исключением, вероятно, оптимизации). Вы можете видеть, что класс/папка названы "compiler" в обоих Angular и TS.

Компилятор angular на самом деле не связан с компилятором TypeScript. Это очень разные компиляторы.

Есть ли отдельный компилятор Angular? Что он компилирует?

У 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 AOT и JIT.

Задача компилятора модуля состоит в создании фабрики модулей, которая в основном содержит объединенные определения провайдеров.

Для получения дополнительной информации прочитайте:

person Max Koretskyi    schedule 10.10.2017
comment
Хорошо. Насколько я понимаю, компилятор превращает удобочитаемый код в машинный код. Вы говорите, что здесь не так, это все-таки интерпретируется, и при всем при этом термин компилятор правильный? Если да, моя интерпретация компилятора была неправильной. Википедия доказывает, что вы правы, но мне интересно, почему тогда существует термин транспилятор. С этой точки зрения это звучит совершенно устаревшим. Спасибо за ответ и лекцию! :) - person codepleb; 10.10.2017
comment
@codepleb, см. этот ответ Берги - person Max Koretskyi; 10.10.2017
comment
@codepleb Обратите внимание, что GCC и многие другие компиляторы вообще не создают машинный код. На практике GCC автоматически вызывает системы для создания машинного кода, но код, который он создает без посторонней помощи, представляет собой просто ассемблер, который затем передается внешнему ассемблеру. - person prosfilaes; 10.10.2017
comment
@AngularInDepth.com, не могли бы вы сократить панель заголовка на своем веб-сайте, пожалуйста :) - person omeralper; 11.10.2017
comment
@omeralper, что ты имеешь в виду под сокращением? что именно вам кажется неудобным? - person Max Koretskyi; 11.10.2017
comment
@AngularInDepth.com заголовок огромен, из-за него веб-сайт трудно читать. Сделайте его одной строкой и удалите нижний колонтитул. - person omeralper; 11.10.2017
comment
@omeralper, блог angluarindepth.com размещен на платформе medium.com. Возможности настройки очень ограничены. Я не могу изменить макет заголовка - person Max Koretskyi; 11.10.2017
comment
@codepleb Этот ответ намного лучше и фактически отвечает на ваш вопрос. Еще есть время пересмотреть свое первоначальное решение. - person async; 11.10.2017
comment
@codepleb нет веской причины для существования или существования термина «транспилятор», все, что он делает, - это вводит в заблуждение. - person Leushenko; 11.10.2017
comment
@async Принятый ответ отвечает на мой вопрос на 100% и более компактен, чем этот. Мне нравятся оба, конечно, но когда я ищу SO для конкретного вопроса, мне нравится, когда ответы, которые я нахожу, короткие и точные. Я согласен, что здесь очень хорошие примеры и все такое, но принятый ответ был прямым ответом на то, что я пытался спросить. Первое предложение было в основном ответом, который я искал, а не объяснением проблемы, в то время как ответ на реальную проблему находится где-то посередине. Я знаю, что это звучит как ленивое оправдание, но SO — это компактность/простота/прямолинейность imho. - person codepleb; 20.10.2017
comment
Можете ли вы ответить, как Angular строится и работает в деталях? Вот вопрос. - person Shaiju T; 26.02.2018
comment
@stom, извините, этот вопрос слишком широк. Хотя ответ, получивший наибольшее количество голосов, довольно хорош - person Max Koretskyi; 26.02.2018
comment
@AngularInDepth.com, Да, я понимаю :), если возможно, вы можете написать о своих выводах в своем блоге на среднем уровне, возможно, это поможет другим. - person Shaiju T; 26.02.2018

Typescript транслируется в JS. Затем идет встряхивание дерева, "менее" (необязательно) и что еще в процессе создания развертывания. Но ничего подобного (афаик) не имеет ничего общего с «компиляцией». Все объединяется и сильно оптимизируется, но на самом деле не компилируется, верно?

Компиляция означает преобразование программы, написанной на языке 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 находятся примерно на одном уровне абстракции, мы называем это транспилером, и
  • если 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) не является родным.

person Jörg W Mittag    schedule 10.10.2017
comment
+1 за глубокое объяснение концепции компиляции и, если бы я мог, еще +1 за эти пункты. Очень полезно. - person Pedro A; 11.10.2017
comment
Хотя, должен сказать, технически это не отвечает на вопрос в заголовке... Тем не менее, заслуженный +1 от меня! - person Pedro A; 11.10.2017
comment
Я согласен, что это неявно, но ответ на вопрос в заголовке - все, что перечисляет OP как не компиляция, - это то, что такое угловая компиляция. - person Jörg W Mittag; 11.10.2017
comment
Действительно хорошее объяснение того, как на самом деле речь идет о соглашениях об именах, а не о существенной разнице. Возможно, можно было бы улучшить, упомянув микрокод - чтобы указать, что даже на уровне машинного кода вы не «на металле» ... - person AakashM; 11.10.2017
comment
Я как-то помню, как узнал, что такое компилятор. Если бы кто-нибудь сказал мне тогда, что компилятор — это синоним транслятора кода, было бы намного проще понять, для чего он нужен и зачем он нам нужен. Конечно, с сегодняшней точки зрения это звучит нелепо, но это лишний раз говорит мне о том, как много пользы можно получить, просто имея подходящего человека, который может его чему-то научить. Спасибо. :) - person codepleb; 11.10.2017
comment
Это фантастический ответ. Кроме того, я нахожу термин ЦП JVM весьма забавным… кто теперь виртуальная машина? - person wchargin; 11.10.2017

Получение кода, который вы написали для запуска в браузере, включает в себя две вещи:

1) Преобразование Typescript в JavaScript. Это своего рода решаемая проблема. Я думаю, что они просто используют веб-пакет.

2) Компиляция угловых абстракций в JavaScript. Я имею в виду такие вещи, как компоненты, каналы, директивы, шаблоны и т. д. Это то, над чем работает основная команда angular.

Если вас действительно интересует вторая часть, компилятор angular, посмотрите, как автор компилятора Тобиас Бош объясняет Компилятор Angular на AngularConnect 2016.

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

person Nathan Cooper    schedule 10.10.2017

угловой компилятор

Одним из наиболее важных изменений по сравнению с Angular 4 и 5 является то, что компилятор был переписан быстрее и тщательнее. В прошлом приложения Angular использовали то, что мы называем компиляцией Just-in-Time (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). «Angular: вверх и вниз».

  • Уилкен, Дж. (2018). «Угловой в действии».

person Tiago Martins Peres 李大仁    schedule 25.10.2019