Apa yang "kompilasi" angular compiler?

88

Saya ditanyai hari ini dan tidak dapat memberikan jawaban yang tepat.

Transparansi ketikan ke JS. Lalu ada getar pohon, "kurang" (opsional) dan apa lagi dalam proses membuat penerapan. Tapi tidak ada yang seperti itu (afaik) yang ada hubungannya dengan "kompilasi". Semuanya dibundel dan sangat dioptimalkan, tetapi sebenarnya tidak dikompilasi, bukan?

Bahkan ada kompiler "sebelumnya", yang benar-benar berfungsi dengan baik. Apa yang saya lewatkan

Javascript sendiri masih diartikan kan?

codepleb
sumber
6
Saya setuju dengan "tidak benar-benar mengkompilasi". Pada dasarnya, ini adalah masalah definisi kompilasi . Beberapa lebih suka menggunakan kata transpilation untuk menandai transformasi dari TypeScript ke JavaScript. Tapi ya, pada intinya, peran compiler Typecript hanya untuk menghasilkan Javascript dari Typecript.
Pac0
6
@ Pac0 Saya mungkin salah paham di sini, tetapi jika TypeScript ke JavaScript adalah transpilasi, bukankah GCC akan menjadi transpiler kode C ke mesin? Bagaimana Anda mendefinisikan perbedaan antara transpiler dan compiler?
11684
24
transpiler adalah penyusun
pengguna253751
5
Lihat Apa yang dimaksud orang ketika mereka mengatakan "transpiler"? (dan tindak lanjut "Lima belas kompiler pertama saya" ) (dari seseorang yang bekerja pada kompiler), yang berpendapat bahwa "kompilator" adalah kata yang baik untuk digunakan untuk hal-hal seperti ini.
ShreevatsaR
2
Javascript sendiri masih di intepret kan? - tidak lagi, itu dikompilasi menjadi kode mesin dengan cepat oleh mesin V8
Max Koretskyi

Jawaban:

91

Anda menganggap kompilasi berarti mengambil kode sumber dan menghasilkan kode mesin, kode level rendah, dll. Tetapi kompilasi sebenarnya hanya berarti mengambil satu kode sumber dan mengubahnya menjadi kode lain. Jadi sepertinya masuk akal untuk mengatakan bahwa mengambil Typecript dan memproduksi JavaScript adalah bentuk kompilasi. Ini tidak berbeda dengan apa yang (misalnya) c # lakukan ketika dikompilasi ke dalam bahasa IL.

Karena itu, saya akan mengatakan kata yang lebih baik untuk ini adalah Transpiling . Saya menyarankan agar compiler Typecript lebih baik dijelaskan sebagai Transpiler.

Perbedaannya tidak kentara dan transpiler dapat dianggap sebagai jenis penyusun; tetapi bahasa yang dikompilasi (murni) adalah (biasanya) mengubah bahasa tingkat tinggi ke bahasa tingkat rendah (er) (lebih dekat ke kode mesin), seperti contoh C #. Transpiler mengubah bahasa tingkat tinggi menjadi bahasa tingkat (abstraksi) yang serupa (juga tingkat tinggi). *

Hasil dari kode yang dikompilasi biasanya bukan bahasa yang Anda tulis sendiri . Hasil dari transpiler adalah bahasa tingkat tinggi lainnya. Secara teori, Anda dapat menulis IL (sebagai contoh) tetapi IL ini benar-benar dirancang untuk diproduksi oleh kompiler dan tidak ada alat atau dukungan untuk melakukan ini, Anda menghasilkan IL hanya dengan mengkompilasi C # / vb.net. Sedangkan Javascript adalah bahasa pemrograman yang dapat digunakan (dan digunakan) dengan sendirinya.

* Banyak peringatan karena definisi dari kata-kata ini dan penggunaannya cukup kabur

Liam
sumber
12
Bukankah JavaScript benar-benar level yang lebih rendah dari TypeScript?
Bergi
3
Meskipun semua yang ada di jawaban ini benar dan bermanfaat, terutama karena definisi kompilasi selalu membingungkan, itu tidak menjawab pertanyaan dalam judul. Jawaban ini berbicara tentang TypeScript saja, sedangkan pertanyaannya tentang Angular. Perbedaannya sangat besar. Sangat mungkin untuk menggunakan Angular tanpa mengetahui bahwa TS adalah sesuatu. Saya terkejut jawaban ini diterima.
Pedro A
3
Pada dasarnya kompilator harus memahami keseluruhan program untuk menghasilkan program lain (yang biasanya melakukan hal yang sama tetapi dalam bahasa lain - ini termasuk kode mesin).
Thorbjørn Ravn Andersen
8
Saya baru saja membacanya dua kali dan tidak dapat menemukan jawaban atas pertanyaannya di sini. Jawabannya ada di bawah.
kuncevic.dev
5
Pertanyaan tersirat yang ditanyakan OP, itulah sebabnya mereka menerima ini, adalah "apakah benar menyebut compiler Angular sebagai compiler?" - dan itulah jawaban jawaban ini. Jadi +1 dari saya. Lihat juga Apa yang orang maksud dengan "transpiler"? dan tindak lanjut "Lima belas kompiler pertama saya" .
ShreevatsaR
70

Anda sepertinya menanyakan tiga pertanyaan sekaligus:

  • Apa perbedaan antara compiler dan transpiler?
  • Apakah Angular dan TypeScript mengimplementasikan compiler atau transpiler?
  • Apakah ada kompiler Angular terpisah? Apa yang dikompilasi?

Apa perbedaan antara compiler dan transpiler?

@ JörgWMittag memberikan jawaban yang sangat bagus untuk pertanyaan ini.

Apakah Angular dan TypeScript mengimplementasikan compiler atau transpiler?

Baik TS dan Angular menerapkan kompiler nyata . Mereka mengikuti tahapan yang sama dari analisis leksikal, parsing, analisis semantik, dan pembuatan kode sebagai kompiler C / C ++ yang menghasilkan kode assembly (kecuali mungkin untuk pengoptimalan). Anda dapat melihat bahwa kelas / folder bernama "compiler" di Angular dan TS .

Kompilator sudut tidak benar-benar terkait dengan kompilator TypeScript. Ini adalah kompiler yang sangat berbeda.

Apakah ada kompiler Angular terpisah? Apa yang dikompilasi?

Angular memiliki dua kompiler:

  • Lihat Compiler
  • Penyusun Modul

Tugas compiler tampilan adalah mengubah template yang Anda tentukan untuk template komponen menjadi representasi internal komponen yang merupakan pabrik tampilan yang kemudian digunakan untuk membuat instance tampilan .

Selain mengubah template, view compiler juga mengkompilasi berbagai informasi metadata dalam bentuk dekorator seperti @HostBinding, @ViewChilddll.

Misalkan Anda menentukan komponen dan templatnya seperti ini:

@Component({
  selector: 'a-comp',
  template: '<span>A Component</span>'
})
class AComponent {}

Dengan menggunakan data ini, kompilator membuat pabrik komponen yang sedikit disederhanakan berikut ini:

function View_AComponent {
  return jit_viewDef1(0,[
      elementDef2(0,null,null,1,'span',...),
      jit_textDef3(null,['My name is ',...])
    ]

Ini menjelaskan struktur tampilan komponen dan digunakan saat membuat instance komponen. Node pertama adalah definisi elemen dan yang kedua adalah definisi teks. Anda dapat melihat bahwa setiap node mendapatkan informasi yang dibutuhkan ketika dibuat instance-nya melalui daftar parameter. Merupakan tugas kompilator untuk menyelesaikan semua dependensi yang diperlukan dan menyediakannya pada waktu proses.

Saya sangat merekomendasikan membaca artikel ini:

Juga, lihat jawaban untuk Apa perbedaan antara kompiler Angular AOT dan JIT.

Tugas compiler modul adalah membuat pabrik modul yang pada dasarnya berisi definisi gabungan dari provider.

Untuk informasi lebih lanjut, baca:

Max Koretskyi
sumber
1
@codepleb, lihat jawaban ini oleh Bergi
Max Koretskyi
1
@codepleb Perhatikan bahwa GCC dan banyak kompiler lainnya tidak menghasilkan kode mesin sama sekali. Dalam praktiknya, GCC secara otomatis memanggil sistem untuk menghasilkan kode mesin, tetapi kode yang dihasilkannya tanpa bantuan eksternal hanyalah perakitan, yang kemudian diserahkan ke assembler eksternal.
prosfilaes
7
@codepleb Jawaban ini jauh lebih unggul dan benar-benar menjawab pertanyaan Anda. Masih ada waktu untuk mempertimbangkan kembali penilaian awal Anda.
asinkron
3
@codepleb tidak ada alasan yang tepat untuk istilah "transpiler" ada atau pernah ada, yang dilakukannya adalah menyesatkan.
Leushenko
2
@ ibu, maaf, pertanyaan itu terlalu luas. Jawaban yang paling disukai adalah cukup bagus
Max Koretskyi
54

Ketikan dikirim ke JS. Lalu ada getar pohon, "kurang" (opsional) dan apa lagi dalam proses membuat penerapan. Tapi tidak ada yang seperti itu (afaik) yang ada hubungannya dengan "kompilasi". Semuanya dibundel dan sangat dioptimalkan, tetapi sebenarnya tidak dikompilasi, bukan?

Kompilasi berarti mengubah program yang ditulis dalam bahasa A menjadi program yang secara semantik setara yang ditulis dalam bahasa B sehingga mengevaluasi program yang dikompilasi sesuai dengan aturan bahasa B (misalnya menafsirkannya dengan penerjemah untuk B ) menghasilkan hasil yang sama dan memiliki efek samping yang sama seperti mengevaluasi program asli sesuai dengan aturan bahasa A (misalnya menafsirkannya dengan penerjemah untuk A ).

Kompilasi hanya berarti menerjemahkan program dari bahasa A ke bahasa B . Hanya itu artinya. (Juga perhatikan bahwa sangat mungkin A dan B menjadi bahasa yang sama.)

Dalam beberapa kasus, kami memiliki nama yang lebih terspesialisasi untuk jenis kompiler tertentu, bergantung pada apa itu A dan B , dan apa yang dilakukan kompilator:

  • jika A dianggap sebagai bahasa assembly dan B dianggap sebagai bahasa mesin, maka kami menyebutnya assembler ,
  • jika A dianggap sebagai bahasa mesin dan B dianggap sebagai bahasa assembly, maka kami menyebutnya disassembler ,
  • jika A dianggap levelnya lebih rendah dari B , maka kami menyebutnya decompiler ,
  • jika A dan B adalah bahasa yang sama, dan program yang dihasilkan lebih cepat atau lebih ringan, maka kami menyebutnya pengoptimal ,
  • jika A dan B adalah bahasa yang sama, dan program yang dihasilkan lebih kecil, maka kita menyebutnya minifier ,
  • jika A dan B adalah bahasa yang sama, dan program yang dihasilkan kurang terbaca, maka kita menyebutnya obfuscator ,
  • jika A dan B dianggap berada pada tingkat abstraksi yang kira-kira sama, maka kami menyebutnya transpiler , dan
  • jika A dan B dianggap berada pada tingkat abstraksi yang kira-kira sama dan program yang dihasilkan mempertahankan pemformatan, komentar, dan maksud pemrogram sedemikian rupa sehingga memungkinkan untuk mempertahankan program yang dihasilkan dengan cara yang sama seperti program aslinya, maka kita memanggil itu alat rekayasa ulang .

Juga, perhatikan bahwa sumber yang lebih lama mungkin menggunakan istilah "terjemahan" dan "penerjemah" daripada "kompilasi" dan "kompilator". Misalnya, C berbicara tentang "unit terjemahan".

Anda juga mungkin menemukan istilah "pemroses bahasa". Ini bisa berarti compiler, interpreter, atau compiler dan interpreter bergantung pada definisinya.

Javascript sendiri masih diartikan kan?

JavaScript adalah sebuah bahasa. Bahasa adalah sekumpulan aturan dan batasan logis. Bahasa tidak diinterpretasikan atau dikompilasi. Bahasa hanya merupakan .

Kompilasi dan interpretasi adalah ciri-ciri seorang compiler atau interpreter (duh!). Setiap bahasa dapat diimplementasikan dengan kompiler dan setiap bahasa dapat diimplementasikan dengan penerjemah. Banyak bahasa memiliki kompiler dan interpreter. Banyak mesin eksekusi berperforma tinggi modern memiliki setidaknya satu kompiler dan setidaknya satu interpreter.

Kedua istilah ini termasuk dalam lapisan abstraksi yang berbeda. Jika bahasa Inggris adalah bahasa yang diketik, "bahasa yang ditafsirkan" akan menjadi kesalahan jenis.

Perhatikan juga bahwa beberapa bahasa tidak memiliki interpreter atau compiler. Ada bahasa yang tidak memiliki implementasi sama sekali. Tetap saja, mereka adalah bahasa, dan Anda dapat menulis program di dalamnya. Anda tidak bisa menjalankannya.

Juga, perhatikan bahwa semuanya ditafsirkan di beberapa titik : jika Anda ingin mengeksekusi sesuatu, Anda harus menafsirkannya. Kompilasi hanya menerjemahkan kode dari satu bahasa ke bahasa lain. Itu tidak menjalankannya. Interpretasi menjalankannya. (Kadang-kadang, ketika penerjemah diimplementasikan di perangkat keras, kami menyebutnya sebagai "CPU", tetapi ini masih merupakan penerjemah.)

Contoh kasus: setiap implementasi JavaScript mainstream yang ada saat ini memiliki kompiler.

V8 dimulai sebagai kompiler murni: ia mengkompilasi JavaScript langsung ke kode mesin asli yang dioptimalkan secara moderat. Kemudian, kompiler kedua ditambahkan. Sekarang, ada dua kompiler: kompiler ringan yang menghasilkan kode yang cukup dioptimalkan tetapi kompilernya sendiri sangat cepat dan menggunakan sedikit RAM. Kompiler ini juga memasukkan kode profil ke dalam kode yang dikompilasi. Kompiler kedua adalah kompiler kelas berat, lebih lambat, lebih mahal, yang, bagaimanapun, menghasilkan kode yang jauh lebih ketat, lebih cepat. Ini juga menggunakan hasil kode profil yang dimasukkan oleh compiler pertama untuk membuat keputusan pengoptimalan dinamis. Selain itu, keputusan kode mana yang akan dikompilasi ulang menggunakan kompilator kedua dibuat berdasarkan informasi profil tersebut. Perhatikan bahwa tidak ada penerjemah yang terlibat. V8 tidak pernah menafsirkan, ia selalu dikompilasi. Itu tidak t bahkan mengandung penerjemah. (Sebenarnya, saya yakin saat ini memang demikian, saya sedang menjelaskan dua iterasi pertama.)

SpiderMonkey mengompilasi JavaScript ke bytecode SpiderMonkey, yang kemudian diinterpretasikan. Interpreter juga membuat profil kode, dan kemudian kode yang paling sering dieksekusi dikompilasi oleh compiler ke kode mesin native. Jadi, SpiderMonkey berisi dua kompiler: satu dari JavaScript ke bytecode SpiderMonkey, dan satu lagi dari bytecode SpiderMonkey ke kode mesin asli.

Hampir semua mesin eksekusi JavaScript (dengan pengecualian V8) mengikuti model kompiler AOT yang mengompilasi JavaScript ke bytecode, dan mesin mode campuran yang beralih antara menafsirkan dan mengompilasi bytecode tersebut.

Anda menulis dalam komentar:

Saya benar-benar berpikir bahwa kode mesin ada di suatu tempat yang terlibat.

Apa artinya "kode mesin"?

Apa bahasa mesin satu orang adalah bahasa perantara orang lain dan sebaliknya? Misalnya, ada CPU yang secara native dapat mengeksekusi bytecode JVM, pada CPU seperti itu, bytecode JVM adalah kode mesin native. Dan ada interpreter untuk kode mesin x86, ketika Anda menjalankan kode mesin x86 tersebut diinterpretasikan bytecode.

Ada interpreter x86 yang disebut JPC yang ditulis di Java. Jika saya menjalankan kode mesin x86 pada JPC yang berjalan pada CPU JVM asli… yang merupakan bytecode dan yang merupakan kode asli? Jika saya mengompilasi kode mesin x86 ke JavaScript (ya, ada alat yang dapat melakukannya) dan menjalankannya di browser pada ponsel saya (yang memiliki CPU ARM), yang merupakan bytecode dan yang merupakan kode mesin asli? Bagaimana jika program yang saya kompilasi adalah emulator SPARC, dan saya menggunakannya untuk menjalankan kode SPARC?

Perhatikan bahwa setiap bahasa menginduksi mesin abstrak, dan merupakan bahasa mesin untuk mesin itu. Jadi, setiap bahasa (termasuk bahasa tingkat sangat tinggi) adalah kode mesin asli. Selain itu, Anda dapat menulis penerjemah untuk setiap bahasa. Jadi, setiap bahasa (termasuk kode mesin x86) tidak asli.

Jörg W Mittag
sumber
4
1 untuk penjelasan mendalam tentang konsep kompilasi, dan jika saya bisa, +1 lagi untuk poin-poin tersebut. Sangat membantu.
Pedro A
1
Meskipun, harus saya katakan, secara teknis ini tidak menjawab pertanyaan dalam judul ... Tapi tetap saja saya mendapatkan +1 dari saya!
Pedro A
Saya setuju itu tersirat, tetapi jawaban atas pertanyaan dalam judul adalah "semua daftar OP yang bukan kompilasi adalah apa itu kompilasi sudut".
Jörg W Mittag
Penjelasan yang sangat bagus tentang bagaimana ini sebenarnya tentang konvensi penamaan dan bukan perbedaan substantif. Mungkin dapat ditingkatkan dengan menyebutkan kode mikro - untuk menunjukkan bahwa bahkan pada tingkat kode mesin, Anda tidak 'pada logam' ...
AakashM
1
Entah bagaimana saya ingat belajar apa itu kompiler. Jika ada orang yang mengatakan kepada saya saat itu, bahwa "compiler" adalah sinonim untuk "penerjemah untuk kode", akan jauh lebih mudah untuk mendapatkan untuk apa atau mengapa kita membutuhkannya. Tentu, ini terdengar konyol dari sudut pandang saat ini, tetapi ini hanya memberi tahu saya sekali lagi betapa seseorang dapat memperoleh manfaat hanya dengan memiliki orang yang tepat untuk mengajarinya sesuatu. Terima kasih. :)
codepleb
18

Mendapatkan kode yang Anda tulis untuk dijalankan di browser melibatkan dua hal:

1) Transpiling Ketikan ke JavaScript . Ini adalah jenis masalah yang terpecahkan. Saya pikir mereka hanya menggunakan webpack.

2) Menyusun abstraksi sudut ke dalam JavaScript . Maksud saya hal-hal seperti komponen, pipa, arahan, templat, dll. Inilah yang dikerjakan tim inti sudut.

Jika Anda benar-benar tertarik dengan bit kedua itu, kompiler sudut, lihat penulis kompiler Tobias Bosch menjelaskan Angular Compiler di AngularConnect 2016 .

Saya pikir ada sedikit kebingungan yang terjadi di sini antara transpiling dan kompilasi. Ini bukan masalah dan masalah selera pribadi, keduanya hanya berubah di antara representasi kode. Tetapi definisi yang saya gunakan secara pribadi adalah bahwa transpilasi berada di antara dua bahasa yang berbeda pada tingkat abstraksi yang serupa (misalnya skrip ketikan ke javascript), sedangkan kompilasi memerlukan penurunan tingkat abstraksi. Saya pikir dari template, komponen, pipa, arahan dll menjadi hanya javascript adalah langkah menuruni tangga abstraksi, dan itulah mengapa ini disebut kompiler.

Nathan Cooper
sumber
1

Penyusun Sudut

Salah satu perubahan terpenting dari Angular 4 menjadi 5 adalah bahwa kompilator telah ditulis ulang menjadi lebih cepat dan lebih menyeluruh. Di masa lalu, aplikasi Angular menggunakan apa yang kami sebut kompilasi Just-in-Time (JIT), di mana aplikasi tersebut dikompilasi saat runtime di browser sebelum dijalankan. Pembaruan kompiler di Angular 5 memajukan perpindahan ke AOT, yang membuat aplikasi berjalan lebih cepat karena melakukan lebih sedikit kompilasi saat menjalankan aplikasi. AOT diaktifkan secara default di semua build produksi sejak Angular CLI versi 1.5.

Katakanlah kita ingin membangun aplikasi untuk penerapan dan menjalankan perintah berikut:

ng build --prod

Beberapa hal terjadi: versi produksi, minifikasi, aset bundel, hashing nama file, goyangan pohon, AOT ... (kita dapat mengaktifkan / menonaktifkan ini menggunakan flag, mis. Aot = false). Singkatnya, flag prod membuat bundel aplikasi yang dioptimalkan dengan melakukan kompilasi AOT menggunakan ngc (Angular compiler) untuk membuat kode yang dioptimalkan dan siap untuk browser ( Ya, itu mengkompilasi template sebelumnya ).

TypeScript Compiler

Kompilator TypeScript, tsc , bertanggung jawab untuk mengompilasi file TypeScript. Ini adalah kompilator yang bertanggung jawab untuk mengimplementasikan fitur TypeScript, seperti tipe statis, dan hasilnya adalah JavaScript murni dari mana kata kunci dan ekspresi TypeScript telah dihapus.

Kompiler TypeScript memiliki dua fitur utama: ini adalah transpiler dan pemeriksa tipe. Kompilator memindahkan TypeScript ke JavaScript. Itu melakukan transformasi berikut pada kode sumber Anda:

  • Hapus semua anotasi jenis.
  • Kompilasi fitur JavaScript baru untuk JavaScript versi lama.
  • Kompilasi fitur TypeScript yang bukan JavaScript standar.

Memanggilnya, kompilator mencari konfigurasi yang dimuat di tsconfig.json (Daftar terperinci dari semua opsi kompilator, bersama dengan nilai default, dapat ditemukan di sini ).

Dalam banyak hal, kompilator TypeScript berfungsi seperti kompiler apa pun. Tetapi ada satu perbedaan yang dapat menarik perhatian yang tidak waspada: secara default, compiler terus memancarkan kode JavaScript bahkan ketika menemui kesalahan. Untungnya, perilaku ini dapat dinonaktifkan dengan menyetel pengaturan noEmitOnErrorkonfigurasi ke true di file tsconfig.json.

Yang perlu diperhatikan : tsc dan ngc memiliki tujuan yang berbeda dan ini bukan tentang memilih satu dari yang lain. Jawaban ini mungkin menarik .

Jawaban ini dibuat berdasarkan konten dari buku-buku berikut

  • Cloe, M. (2018). "Angular 5 Projects: Belajar Membangun Aplikasi Web Satu Halaman Menggunakan 70+ Proyek".

  • Dewey, B., Grossnicklaus, K., Japikse, P. (2017). "Membangun Aplikasi Web dengan Visual Studio 2017: Menggunakan .NET Core dan Modern JavaScript Frameworks".

  • Freeman, A. (2019). "Essential TypeScript: Dari Pemula hingga Pro".

  • Ghiya, P. (2018). "TypeScript Microservices".

  • Iskandar, A., Chivukulu, S. (2019). "Pengembangan Web dengan Angular dan Bootstrap - Edisi Ketiga".

  • Hennessy, K., Arora, C. (2018). "Sudut 6 dengan Contoh".

  • Jansen, R., Wolf, I., Vane, V. (2016). "TypeScript: Pengembangan JavaScript Modern".

  • Mohammed, Z. (2019). "Proyek Sudut".

  • Seshadri, S. (2018). "Angular: Up and Running".

  • Wilken, J. (2018). "Angular in Action".

Tiago Martins Peres 李大仁
sumber