Що «компілює» кутовий компілятор?


88

Мене просили сьогодні, і я не зміг дати належної відповіді.

Транскрипт машинопису до JS. Потім є тремтіння дерева, "менше" (необов'язково) і що ще в процесі розгортання. Але ніщо подібне (afaik) не має нічого спільного з "компіляцією". Все складається в комплекті та сильно оптимізується, але насправді це не компілюється, правда?

Існує навіть компілятор "заздалегідь", який справді робить помітну роботу. Що мені не вистачає?

Сам Javascript все ще інтерпретується, так?


6
Я погоджуюся з "не дуже складанням". По суті, це питання визначення компіляції . Деякі вважають за краще використовувати слово транспіляція для позначення перетворення з TypeScript в JavaScript. Але так, по суті, роль компілятора Typescript полягає лише у створенні Javascript із Typescript.
Pac0

6
@ Pac0 Я, можливо, щось тут не розумію, але якщо TypeScript до JavaScript є транпіляцією, чи не буде GCC C-компілятором машинного коду? Як би ви визначили різницю між компілятором і компілятором?
11684

24
transpilers - компілятори
user253751

5
Подивіться, що люди мають на увазі, коли кажуть "перекладач"? (і продовження “Мої перші п’ятнадцять компіляторів” ) (від когось, хто працює над компілятором), який стверджує, що “компілятор” - це гарне слово для таких речей.
ShreevatsaR

2
Сам Javascript все ще інтерпретується, так? - більше не, він на ходу компілюється в машинний код за допомогою двигуна V8
Макс Корецький

Відповіді:


91

Ви припускаєте, що компіляція означає отримання вихідного коду та створення машинного коду, низькорівневих кодів тощо. Але насправді компіляція просто означає взяти один вихідний код і перетворити його в інший. Тому представляється розумним сказати, що використання Typescript та створення JavaScript - це форма компіляції. Це не відрізняється від того, що (наприклад) робить c #, коли його компілюється на мову IL.

Тим не менш, я б сказав краще слово для цього - Транспілювання . Я вважаю, що компілятор Typescript кращий Typescript описати як Transpiler.

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

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

* Багато застережень, оскільки визначення цих слів та їх використання досить розмиті


12
Хіба JavaScript не суворо нижчий за рівень TypeScript?
Бергі,

3
Хоча у цій відповіді все правильно і корисно, тим більше, що визначення компіляції завжди викликає плутанину, воно не відповідає на заголовне питання. Ця відповідь говорить лише про TypeScript, тоді як питання стосується Angular. Різниця величезна. Цілком можливо використовувати Angular, навіть не підозрюючи, що TS - це річ. Я здивований, що цю відповідь прийняли.
Педро A

3
Компілятор повинен по суті розуміти всю програму, щоб створити іншу програму (яка зазвичай робить те саме, але іншою мовою - сюди входить машинний код).
Thorbjørn Ravn Andersen

8
Я просто прочитав це двічі і не зміг знайти тут відповіді на запитання. Відповідь трохи нижче.
kuncevic.dev

5
Неявне запитання, яке ставив OP, саме тому вони прийняли це, було "чи правильно називати Angular compiler компілятором?" - і саме на це відповідає ця відповідь. Тож +1 від мене. Дивіться також Що мають на увазі люди, коли кажуть "перекладач"? та продовження “Мої перші п’ятнадцять укладачів” .
ShreevatsaR

70

Ви, здається, задаєте три запитання в одному:

  • У чому різниця між компілятором і трансліпером?
  • Чи реалізують Angular та TypeScript компілятори чи транпілятори?
  • Чи існує окремий Angular компілятор? Що він складає?

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

@ JörgWMittag дуже добре відповів на це питання.

Чи реалізують Angular та TypeScript компілятори чи транпілятори?

І TS, і Angular реалізують справжні компілятори. Вони проходять ті самі етапи лексичного аналізу, синтаксичного аналізу, семантичного аналізу та генерації коду, що і компілятори C / C ++, які виробляють код збірки (крім, можливо, для оптимізації). Ви бачите, що клас / папка мають назву "компілятор" як в Angular, так і в TS .

Кутовий компілятор насправді не пов'язаний з компілятором 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-компілятором.

Завдання компілятора модулів полягає у створенні фабрики модулів, яка в основному містить об’єднані визначення постачальників.

Для отримання додаткової інформації читайте:



1
@codepleb Зверніть увагу, що GCC та багато інших компіляторів взагалі не виробляють машинний код. На практиці GCC автоматично викликає системи для створення машинного коду, але код, який він виробляє без сторонньої допомоги, - це просто збірка, яка потім передається зовнішньому асемблеру.
prosfilaes

7
@codepleb Ця відповідь набагато краща і насправді відповідає на ваше запитання. Ще є час переглянути своє первісне судження.
async

3
@codepleb немає жодної вагомої причини для того, щоб термін "transpiler" існував або коли-небудь існував, все це вводить в оману.
Леушенко

2
@stom, вибачте, це запитання занадто широке. Хоча найголосніша відповідь досить гарна
Макс Корецький,

54

Машинопис надходить до 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 сприймаються приблизно на одному рівні абстракції, а отримана програма зберігає форматування, коментарі та намір програміста таким чином, що можна підтримувати отриману програму таким же чином, як і оригінальна програма, тоді ми називаємо це інструмент реінжинірингу .

Також зауважте, що в старих джерелах можуть використовуватися терміни "переклад" та "перекладач" замість "компіляція" та "компілятор". Наприклад, С говорить про "одиниці перекладу".

Ви також можете натрапити на термін "мовний процесор". Це може означати як компілятор, інтерпретатор, так і компілятори та інтерпретатори, залежно від визначення.

Сам Javascript все ще інтерпретується, так?

JavaScript - це мова. Мови - це сукупність логічних правил та обмежень. Мови не інтерпретуються та не компілюються. Мови просто є .

Компіляція та інтерпретація - це риси упорядника чи інтерпретатора (duh!). Кожна мова може бути реалізована за допомогою компілятора, а кожна мова - за допомогою інтерпретатора. Багато мов мають як компілятори, так і інтерпретатори. У багатьох сучасних високопродуктивних механізмах виконання є принаймні один компілятор і принаймні один інтерпретатор.

Ці два терміни належать до різних шарів абстракції. Якби англійська мова була типовою, "інтерпретована мова" була б помилкою типу.

Зауважте також, що деякі мови не мають ні інтерпретатора, ні компілятора. Є мови, які взагалі не мають реалізації. І все-таки це мови, і ви можете писати програми на них. Ви просто не можете їх запускати.

Також зауважте, що все в якийсь момент інтерпретується : якщо ви хочете щось виконати, ви повинні інтерпретувати це. Компіляція просто перекладає код з однієї мови на іншу. Це не запускає його. Інтерпретація запускає його. (Іноді, коли інтерпретатор реалізований в апаратному забезпеченні, ми називаємо його "ЦП", але це все одно інтерпретатор.)

Приклад: кожна окрема існуюча на сьогодні реалізація 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 CPU), який є байт-кодом, а який є власним машинним кодом? Що робити, якщо програма, яку я складаю, є емулятором SPARC, і я використовую його для запуску коду SPARC?

Зверніть увагу, що кожна мова викликає абстрактну машину і є машинною мовою для цієї машини. Отже, кожна мова (включаючи мови високого рівня) є рідним машинним кодом. Крім того, ви можете написати перекладача для будь-якої мови. Отже, кожна мова (включаючи машинний код x86) не є рідною.


4
+1 за глибоке пояснення концепції компіляції, і якщо я міг, ще +1 за ці пункти. Дуже корисний.
Педро A

1
Хоча, мушу сказати, технічно це не відповідає на заголовне питання ... Однак все-таки заслужений +1 від мене!
Педро A

Я погоджуюсь, що це неявно, але відповідь на запитання у заголовку - "все, що ОП перераховує як не компіляцію, це те, що таке кутова компіляція".
Jörg W Mittag

Дійсно гарне пояснення того, як це насправді стосується конвенцій імен, а не суттєвої різниці. Можливо, це можна покращити, згадавши мікрокод - щоб зазначити, що навіть на рівні машинного коду ви не «в металі» ...
AakashM

1
Я якось пам’ятаю, як дізнався, що таке компілятор. Якби хтось сказав мені тоді, що "компілятор" є синонімом "перекладача для коду", було б набагато простіше отримати те, для чого він потрібний, і для чого він нам потрібен. Звичайно, це звучить безглуздо з нинішніх позицій, але це просто ще раз підказує мені, наскільки корисною може бути лише наявність потрібної людини, яка його чогось навчить. Дякую. :)
codepleb

18

Отримання коду, який ви написали для запуску в браузері, включає дві речі:

1) Транспіляція машинопису в JavaScript . Це свого роду вирішена проблема. Я думаю, що вони просто використовують webpack.

2) Компіляція кутових абстракцій у JavaScript . Я маю на увазі такі речі, як компоненти, трубопроводи, директиви, шаблони і т. Д. Це те, над чим працює кутова основна команда.

Якщо вас справді цікавить цей другий біт, кутовий компілятор, автор компілятора годинника Тобіас Бош пояснює Angular Compiler на AngularConnect 2016 .

Думаю, тут виникає певна плутанина між транпіляцією та компіляцією. Це як би не має значення, і це питання особистого смаку, вони обидва просто трансформуються між представленнями коду. Але визначення, яке я особисто використовую, полягає в тому, що транпіляція відбувається між двома різними мовами на однаковому рівні абстракції (наприклад, машинопис до javascript), тоді як компіляція вимагає зниження рівня абстракції. Я думаю, що від шаблонів, компонентів, каналів, директив тощо до просто javascript - це крок вниз по сходах абстракції, і тому він називається компілятором.


1

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

Одне з найважливіших змін від 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 compiler) для створення оптимізованого коду, готового для браузера ( так, він попередньо компілює шаблони) ).

Компілятор 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+ проектів".

  • Dewey, B., Grossnicklaus, K., Japikse, P. (2017). "Створення веб-додатків за допомогою Visual Studio 2017: Використання .NET Core та сучасних платформ JavaScript".

  • Фрімен, А. (2019). Msgstr "Основний TypeScript: від початківця до професіонала".

  • Гія, П. (2018). "Мікросервіси TypeScript".

  • Іскандар А., Чівукулу С. (2019). "Веб-розробка за допомогою Angular та Bootstrap - третє видання".

  • Хеннессі, К., Арора, К. (2018). "Кутовий 6 на прикладі".

  • Янсен, Р., Вольф, І., Вейн, В. (2016). "TypeScript: Сучасна розробка JavaScript".

  • Мохаммед, З. (2019). "Кутові проекти".

  • Шешадрі, С. (2018). "Кутовий: вгору і працює".

  • Вілкен, Дж. (2018). "Кутовий в дії".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.