Меня спросили об этом сегодня, и я не смог дать должного ответа.
Машинопись преобразуется в JS. Затем идет тряска дерева, «меньше» (необязательно) и что еще в процессе развертывания. Но ничего подобного (afaik) не имеет ничего общего с "компиляцией". Все объединяется и сильно оптимизируется, но на самом деле не компилируется, верно?
Есть даже компилятор «впереди времени», который действительно делает заметную работу. Что мне не хватает?
Сам Javascript все еще интерпретируется, верно?
Ответы:
Вы предполагаете, что компиляция означает взятие исходного кода и создание машинного кода, низкоуровневых кодов и т.д. Но на самом деле компиляция означает просто взять один исходный код и превратить его в другой. Поэтому кажется разумным сказать, что использование Typescript и создание JavaScript - это форма компиляции. Это не отличается от того, что (например) делает C #, когда он скомпилирован в язык IL.
Тем не менее, я бы сказал более подходящее слово для этого - Транспилинг . Я бы посоветовал лучше описать компилятор Typescript как Transpiler.
Разница невелика, и транспилятор можно рассматривать как тип компилятора; но (чистый) скомпилированный язык (обычно) превращает язык высокого уровня в язык низкого (er) уровня (ближе к машинному коду), как в примере C #. Транспилер превращает язык высокого уровня в язык аналогичного уровня (абстракции) (также высокого уровня). *
Результат скомпилированного кода обычно не является языком, который вы бы написали сами . Результатом транспилятора является еще один язык высокого уровня. Теоретически вы можете написать IL (в качестве примера), но на самом деле он разработан для создания компилятором, и для этого нет инструментов или поддержки, вы создаете IL путем компиляции только C # / vb.net. В то время как Javascript - это полезный (и используемый) язык программирования сам по себе.
* Множество предостережений, поскольку определения этих слов и их использования довольно расплывчаты.
источник
Кажется, вы задаете три вопроса в одном:
@ JörgWMittag дал очень хороший ответ на этот вопрос.
И TS, и Angular реализуют настоящие компиляторы. Они проходят те же этапы лексического анализа, синтаксического анализа, семантического анализа и генерации кода, что и компиляторы C / C ++, которые производят ассемблерный код (за исключением, вероятно, оптимизации). Вы можете видеть, что класс / папка названы «компилятор» как в Angular, так и в TS .
Компилятор angular на самом деле не имеет отношения к компилятору 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 AOT и JIT.
Задача компилятора модуля - создать фабрику модулей, которая в основном содержит объединенные определения поставщиков.
Для получения дополнительной информации прочтите:
источник
Компиляция означает преобразование программы, написанной на языке A, в семантически эквивалентную программу, написанную на языке B, таким образом, что оценка скомпилированной программы в соответствии с правилами языка B (например, интерпретация ее с помощью интерпретатора для B ) дает тот же результат и имеет те же побочные эффекты, что и при оценке исходной программы в соответствии с правилами языка A (например, при ее интерпретации с помощью интерпретатора для A ).
Составление просто означает перевод программы с языка А на язык Б . Это все, что это значит. (Также обратите внимание, что A и B могут быть одним и тем же языком.)
В некоторых случаях у нас есть более специализированные имена для определенных типов компиляторов, в зависимости от того, что такое A и B , и что делает компилятор:
Также обратите внимание, что старые источники могут использовать термины «перевод» и «переводчик» вместо «компиляция» и «компилятор». Например, C говорит о «единицах перевода».
Вы также можете встретить термин «языковой процессор». Это может означать либо компилятор, либо интерпретатор, либо оба компилятора и интерпретатора в зависимости от определения.
JavaScript - это язык. Языки - это набор логических правил и ограничений. Языки не интерпретируются и не компилируются. Языки просто есть .
Компиляция и интерпретация - это особенности компилятора или интерпретатора (да!). Каждый язык может быть реализован с помощью компилятора, и каждый язык может быть реализован с помощью интерпретатора. Многие языки имеют как компиляторы, так и интерпретаторы. Многие современные высокопроизводительные механизмы выполнения имеют как минимум один компилятор и как минимум один интерпретатор.
Эти два термина относятся к разным уровням абстракции. Если бы английский был типизированным языком, «интерпретируемый язык» был бы ошибкой типа.
Также обратите внимание, что в некоторых языках нет ни интерпретатора, ни компилятора. Есть языки, у которых вообще нет реализации. Тем не менее, это языки, и на них можно писать программы. Вы просто не можете их запустить.
Также обратите внимание, что в какой-то момент все интерпретируется : если вы хотите что-то выполнить, вы должны это интерпретировать. Компиляция просто переводит код с одного языка на другой. Это не работает. Это управляет интерпретация . (Иногда, когда интерпретатор реализован на оборудовании, мы называем его «ЦП», но это все равно интерпретатор.)
Показательный пример: каждая существующая в настоящее время основная реализация JavaScript имеет компилятор.
V8 начинался как чистый компилятор: он компилировал JavaScript прямо в умеренно оптимизированный машинный код. Позже был добавлен второй компилятор. Теперь есть два компилятора: легкий компилятор, который производит умеренно оптимизированный код, но сам компилятор очень быстр и использует мало оперативной памяти. Этот компилятор также вставляет код профилирования в скомпилированный код. Второй компилятор - это более тяжелый, медленный и более дорогой компилятор, который, однако, создает гораздо более жесткий и более быстрый код. Он также использует результаты кода профилирования, введенного первым компилятором, для принятия решений по динамической оптимизации. Кроме того, решение, какой код перекомпилировать с использованием второго компилятора, принимается на основе этой информации о профилировании. Обратите внимание, что переводчик ни разу не задействован. V8 никогда не интерпретирует, он всегда компилируется. Это не t даже есть интерпретатор. (На самом деле, я считаю, что сейчас это так, я описываю первые две итерации.)
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) Транспортировка машинописного текста в JavaScript . Это своего рода решенная проблема. Я думаю, они просто используют webpack.
2) Компиляция угловых абстракций в JavaScript . Я имею в виду такие вещи, как компоненты, каналы, директивы, шаблоны и т. Д. Это то, над чем работает команда angular core.
Если вас действительно интересует второй бит, компилятор angular, посмотрите , как автор компилятора Тобиас Бош объясняет Angular Compiler на AngularConnect 2016 .
Я думаю, здесь происходит некоторая путаница между транспиляцией и компиляцией. Это вроде как не имеет значения и зависит от личного вкуса, они оба просто трансформируют представления кода. Но определение, которое я использую лично, заключается в том, что транспиляция осуществляется между двумя разными языками на одинаковом уровне абстракции (например, машинописный текст в javascript), тогда как компиляция требует понижения уровня абстракции. Я думаю, что переход от шаблонов, компонентов, каналов, директив и т. Д. К простому javascript - это шаг вниз по лестнице абстракции, и поэтому он называется компилятором.
источник
Угловой компилятор
Одно из самых важных изменений от Angular 4 к 5 - компилятор был переписан быстрее и тщательнее. В прошлом приложения Angular использовали то, что мы называем JIT-компиляцией, когда приложение компилировалось во время выполнения в браузере перед запуском. Обновления компилятора в Angular 5 продвинули переход к AOT, что сделало приложение быстрее, поскольку оно выполняет меньше компиляции при запуске приложения. AOT включается по умолчанию в любой производственной сборке, начиная с версии 1.5 Angular CLI.
Допустим, мы хотим создать приложение для развертывания и выполнить следующую команду:
Происходит несколько вещей: производственная версия, минификация, объединяет ресурсы, хеширование имени файла, встряхивание дерева, AOT ... (мы можем включить / отключить это с помощью флагов, например, aot = false). Короче говоря, флаг prod создает оптимизированный пакет приложения, выполняя компиляцию AOT с использованием ngc (компилятор Angular) для создания оптимизированного кода, готового для браузера ( да, он предварительно компилирует шаблоны ).
Компилятор TypeScript
Компилятор TypeScript, tsc , отвечает за компиляцию файлов TypeScript. Именно компилятор отвечает за реализацию функций TypeScript, таких как статические типы, и в результате получается чистый JavaScript, из которого были удалены ключевые слова и выражения TypeScript.
Компилятор TypeScript имеет две основные функции: это транспилятор и средство проверки типов. Компилятор преобразует 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). «Угловой в действии».
источник