Eksternal dan Ekspor

Tujuan Eksternal

Eksternal adalah deklarasi yang memberi tahu Closure Compiler nama simbol yang tidak boleh diganti namanya selama kompilasi lanjutan. Disebut ekstensi karena simbol ini paling sering ditentukan oleh kode di luar kompilasi, seperti kode native, atau library pihak ketiga. Oleh karena itu, ekstensi juga sering kali memiliki anotasi jenis, sehingga Closure Compiler dapat memeriksa penggunaan Anda atas simbol-simbol tersebut.

Secara umum, yang terbaik adalah menganggap ekstensi sebagai kontrak API antara pelaksana dan konsumen dari beberapa bagian kode yang dikompilasi. Ekstensi menentukan apa yang dijanjikan oleh pelaksana, dan apa yang dapat diandalkan oleh konsumen. Kedua belah pihak memerlukan salinan kontrak.

Eksternal mirip dengan file header dalam bahasa lain.

Sintaksis Eksternal

Eksternal adalah file yang sangat mirip dengan JavaScript normal yang dianotasi untuk Closure Compiler. Perbedaan utamanya adalah kontennya tidak pernah dicetak sebagai bagian dari output yang dikompilasi, sehingga tidak ada nilai yang bermakna, hanya nama dan jenis.

Berikut adalah contoh file eksternal untuk library sederhana.

// The `@externs` annotation is the best way to indicate a file contains externs.

/**
 * @fileoverview Public API of my_math.js.
 * @externs
 */

// Externs often declare global namespaces.

const myMath = {};

// Externs can declare functions, most importantly their names.

/**
 * @param {number} x
 * @param {number} y
 * @return {!myMath.DivResult}
 */
myMath.div = function(x, y) {};  // Note the empty body.

// Externs can contain type declarations, such as classes and interfaces.

/** The result of an integer division. */
myMath.DivResult = class {

  // Constructors are special; member fields can be declared in their bodies.

  constructor() {
    /** @type {number} */
    this.quotient;
    /** @type {number} */
    this.remainder;
  }

  // Methods can be declared as usual; their bodies are meaningless though.

  /** @return {!Array<number>} */
  toPair() {}

};

// Fields and methods can also be declared using prototype notation.

/**
 * @override
 * @param {number=} radix
 */
myMath.DivResult.prototype.toString = function(radix) {};
    

Bendera --externs

Secara umum, anotasi @externs adalah cara terbaik untuk memberi tahu compiler bahwa file berisi extern. File tersebut dapat disertakan sebagai file sumber normal menggunakan flag command line --js,

Namun, ada cara lain yang lebih lama untuk menentukan file ekstensi. Flag command line --externs dapat digunakan untuk meneruskan file ekstern. Metode ini tidak direkomendasikan.

Menggunakan Eksternal

Bagian eksternal dari atas dapat digunakan sebagai berikut.

/**
 * @fileoverview Do some math.
 */

/**
 * @param {number} x
 * @param {number} y
 * @return {number}
 */
export function greatestCommonDivisor(x, y) {
  while (y != 0) {
    const temp = y;
    // `myMath` is a global, it and `myMath.div` are never renamed.
    const result = myMath.div(x, y);
    // `remainder` is also never renamed on instances of `DivResult`.
    y = result.remainder;
    x = temp;
  }
  return x;
}
    

Cara Menyertakan Externs dengan Closure Compiler Service API

Aplikasi Closure Compiler dan API layanan Closure Compiler mengizinkan deklarasi eksternal. Namun, UI layanan Closure Compiler tidak menyediakan elemen antarmuka untuk menentukan file ekstensi.

Ada tiga cara untuk mengirim deklarasi eksternal ke layanan Closure Compiler:

  • Teruskan file yang berisi anotasi @externs sebagai file sumber.
  • Teruskan JavaScript ke layanan Compiler Closure di parameter js_externs.
  • Teruskan URL file JavaScript ke layanan Closure Compiler dalam parameter externs_url.

Satu-satunya perbedaan antara penggunaan js_externs dan penggunaan externs_url adalah cara JavaScript dikomunikasikan ke layanan Closure Compiler.

Tujuan Ekspor

Ekspor adalah mekanisme lain untuk memberikan nama yang konsisten pada simbol setelah kompilasi. Alat tersebut kurang berguna dibandingkan eksternal dan sering kali membingungkan. Untuk semua kasus kecuali yang sederhana, sebaiknya dihindari.

Ekspor bergantung pada fakta bahwa Closure Compiler tidak mengubah literal string. Dengan menetapkan objek ke properti yang diberi nama menggunakan literal, objek akan tersedia melalui nama properti tersebut bahkan setelah kompilasi.

Berikut adalah contoh sederhana.

/**
 * @fileoverview Do some math.
 */

// Note that the concept of module exports is totally unrelated.

/** @return {number} */
export function myFunction() {
  return 5;
}

// This assignment ensures `myFunctionAlias` will be a global alias exposing `myFunction`,
// even after compilation.

window['myFunctionAlias'] = myFunction;
    

Jika Anda menggunakan Library Closure, ekspor juga dapat dideklarasikan menggunakan fungsi goog.exportSymbol dan goog.exportProperty.

Informasi selengkapnya tersedia dalam dokumentasi Library Closure untuk fungsi ini. Namun, perhatikan bahwa mereka memiliki dukungan compiler khusus dan akan diubah sepenuhnya dalam output yang dikompilasi.

Masalah terkait Ekspor

Ekspor berbeda dari eksternal karena mereka hanya membuat alias terbuka yang dapat dirujuk oleh konsumen. Dalam kode yang telah dikompilasi, simbol yang diekspor akan tetap diganti namanya. Oleh karena itu, simbol yang diekspor harus konstan, karena menetapkan kembali simbol tersebut dalam kode akan menyebabkan alias yang diekspos mengarah ke hal yang salah.

Kemudahan penggantian nama ini sangat rumit sehubungan dengan properti instance yang diekspor.

Secara teori, ekspor dapat mengizinkan ukuran kode yang lebih kecil dibandingkan dengan ekstensi, karena nama yang panjang tetap dapat diubah menjadi yang lebih singkat dalam kode Anda. Dalam praktiknya, peningkatan ini sering kali tidak terlalu signifikan, dan tidak membenarkan kebingungan yang terjadi saat mengekspor.

Ekspor juga tidak menyediakan API bagi konsumen untuk diikuti dengan cara yang dapat dilakukan oleh ekstensi. Dibandingkan dengan ekspor, extern mendokumentasikan simbol yang ingin diekspos, jenisnya, dan memberikan tempat untuk menambahkan informasi penggunaan. Selain itu, jika konsumen Anda juga menggunakan Closure Compiler, mereka memerlukan alat ekstensi untuk dikompilasi.