外部人材とエクスポート
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
インターンの目的
extern は、高度なコンパイル中に名前を変更しない記号の名前を Closure Compiler に伝える宣言です。これらのシンボルは、コンパイル外のコード(ネイティブ コードやサードパーティ ライブラリなど)で定義されることが多いため、extern と呼ばれます。そのため、Closure Compiler がこれらのシンボルの使用を型チェックできるように、externs には型アノテーションも含まれていることがよくあります。
一般に、extern は、コンパイル済みコードの一部を実装する側と使用する側との間の API 契約と考えるのが最適です。extern は、実装者が提供することを約束する内容と、コンシューマーが使用を依存できる内容を定義します。両者に契約書のコピーが必要です。
extern は、他の言語のヘッダー ファイルに似ています。
Externs の構文
externs は、Closure Compiler 用にアノテーションが付けられた通常の JavaScript とよく似たファイルです。主な違いは、コンパイルされた出力の一部として内容が出力されないため、値は意味がなく、名前と型のみが意味を持つことです。
次に、簡単なライブラリの externs ファイルの例を示します。
// 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) {};
--externs
フラグ
一般的に、@externs
アノテーションは、ファイルに extern が含まれていることをコンパイラに通知する最良の方法です。このようなファイルは、--js
コマンドライン フラグを使用して通常のソースファイルとして含めることができます。
ただし、extern ファイルを指定する別の古い方法もあります。--externs
コマンドライン フラグを使用して、externs ファイルを明示的に渡すことができます。この方法はおすすめしません。
Extern の使用
上記の extern は次のように使用できます。
/**
* @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;
}
エクスポートの目的
エクスポートは、コンパイル後にシンボルに一貫した名前を付けるためのもう 1 つのメカニズムです。extern ほど有用ではなく、混乱を招くことがよくあります。単純なケースを除き、使用は避けるのが最善です。
エクスポートは、Closure Compiler が文字列リテラルを変更しないという事実に基づいています。リテラルを使用して命名されたプロパティにオブジェクトを割り当てると、コンパイル後もそのプロパティ名でオブジェクトを使用できます。
以下に簡単な例を示します。
/**
* @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;
Closure Library を使用している場合は、goog.exportSymbol
関数と goog.exportProperty
関数を使用してエクスポートを宣言することもできます。
詳しくは、これらの関数の Closure Library のドキュメントをご覧ください。ただし、これらは特別なコンパイラ サポートがあり、コンパイルされた出力で完全に変換されることに注意してください。
エクスポートに関する問題
エクスポートは、コンシューマーが参照する公開されたエイリアスのみを作成するという点で、extern とは異なります。コンパイルされたコード内では、エクスポートされたシンボルは引き続き名前変更されます。このため、エクスポートされたシンボルは定数である必要があります。コードで再割り当てすると、公開されたエイリアスが間違ったものを指すことになります。
この名前変更の微妙な違いは、エクスポートされたインスタンス プロパティに関して特に複雑です。
理論上、エクスポートでは、長い名前をコード内で短い名前に変更できるため、externs よりもコードサイズを小さくできます。実際には、これらの改善は非常に小さいことが多く、エクスポートによって生じる混乱を正当化するものではありません。
また、エクスポートでは、externs のようにコンシューマーが従う API は提供されません。エクスポートと比較して、externs では、公開するシンボルとその型がドキュメント化され、使用情報を追加する場所が提供されます。また、コンシューマーが Closure Compiler を使用している場合は、コンパイル対象の externs が必要になります。
特に記載のない限り、このページのコンテンツはクリエイティブ・コモンズの表示 4.0 ライセンスにより使用許諾されます。コードサンプルは Apache 2.0 ライセンスにより使用許諾されます。詳しくは、Google Developers サイトのポリシーをご覧ください。Java は Oracle および関連会社の登録商標です。
最終更新日 2025-07-26 UTC。
[null,null,["最終更新日 2025-07-26 UTC。"],[[["\u003cp\u003eExterns are declarations that inform Closure Compiler about external symbols (like those from native code or third-party libraries) that should not be renamed during compilation.\u003c/p\u003e\n"],["\u003cp\u003eThey act as an API contract, defining what symbols are provided and ensuring type safety by including type annotations.\u003c/p\u003e\n"],["\u003cp\u003eExterns are primarily defined in separate files using the \u003ccode\u003e@externs\u003c/code\u003e annotation, similar to header files in other languages.\u003c/p\u003e\n"],["\u003cp\u003eWhile exports offer an alternative for exposing symbols, they are less versatile than externs and can introduce complexities, making externs generally preferred.\u003c/p\u003e\n"],["\u003cp\u003eExports create aliases for symbols, while externs provide comprehensive API documentation and type information for external code interaction.\u003c/p\u003e\n"]]],[],null,["# Externs and Exports\n\nPurpose of Externs\n------------------\n\n\nExterns are declarations that tell Closure Compiler the names of\nsymbols that should not be renamed during advanced compilation.\nThey are called externs because these symbols are most often defined by\ncode outside the compilation, such a native code, or third-party\nlibraries. For this reason, externs often also have type annotations,\nso that Closure Compiler can typecheck your use of those symbols.\n\n\nIn general, it is best to think of externs as an API contract between\nthe implementor and the consumers of some piece of compiled code. The\nexterns define what the implementor promises to supply, and what the\nconsumers can depend on using. Both sides need a copy of the contract.\n\nExterns are similar to header files in other languages. \n\nExterns Syntax\n--------------\n\n\nExterns are files that look very much like normal JavaScript annotated\nfor Closure Compiler. The main difference is that their contents are never printed\nas part of the compiled output, so none of the values are meaningful,\nonly the names and types.\n\nBelow is an example of an externs file for a simple library. \n\n```gdscript\n// The `@externs` annotation is the best way to indicate a file contains externs.\n\n/**\n * @fileoverview Public API of my_math.js.\n * @externs\n */\n\n// Externs often declare global namespaces.\n\nconst myMath = {};\n\n// Externs can declare functions, most importantly their names.\n\n/**\n * @param {number} x\n * @param {number} y\n * @return {!myMath.DivResult}\n */\nmyMath.div = function(x, y) {}; // Note the empty body.\n\n// Externs can contain type declarations, such as classes and interfaces.\n\n/** The result of an integer division. */\nmyMath.DivResult = class {\n\n // Constructors are special; member fields can be declared in their bodies.\n\n constructor() {\n /** @type {number} */\n this.quotient;\n /** @type {number} */\n this.remainder;\n }\n\n // Methods can be declared as usual; their bodies are meaningless though.\n\n /** @return {!Array\u003cnumber\u003e} */\n toPair() {}\n\n};\n\n// Fields and methods can also be declared using prototype notation.\n\n/**\n * @override\n * @param {number=} radix\n */\nmyMath.DivResult.prototype.toString = function(radix) {};\n \n``` \n\n### The `--externs` Flag\n\n\nGenerally, the `@externs` annotation is the best way to inform\nthe compiler that a file contains externs. Such files can be included\nas normal source files using the `--js` command-line flag,\n\n\nHowever, there is another, older way, to specify externs files. The\n`--externs` command-line flag can be used to pass externs\nfiles explicitly. This method is not recommended. \n\nUsing Externs\n-------------\n\nThe externs from above can be consumed as follows. \n\n```mysql\n/**\n * @fileoverview Do some math.\n */\n\n/**\n * @param {number} x\n * @param {number} y\n * @return {number}\n */\nexport function greatestCommonDivisor(x, y) {\n while (y != 0) {\n const temp = y;\n // `myMath` is a global, it and `myMath.div` are never renamed.\n const result = myMath.div(x, y);\n // `remainder` is also never renamed on instances of `DivResult`.\n y = result.remainder;\n x = temp;\n }\n return x;\n}\n \n``` \n\nPurpose of Exports\n------------------\n\n\nExports are another mechanism for giving symbols consistent names after\ncompilation. They are less useful than externs and often confusing. For\nall but simple cases they are best avoided.\n\n\nExports rely on the fact that Closure Compiler doesn't modify string literals.\nBy assigning an object to a property named using a literal, the object will\nbe available through that property name even after compilation.\n\n\nBelow is a simple example. \n\n```mysql\n/**\n * @fileoverview Do some math.\n */\n\n// Note that the concept of module exports is totally unrelated.\n\n/** @return {number} */\nexport function myFunction() {\n return 5;\n}\n\n// This assignment ensures `myFunctionAlias` will be a global alias exposing `myFunction`,\n// even after compilation.\n\nwindow['myFunctionAlias'] = myFunction;\n \n``` \n\nIf you are using Closure Library, exports can also be declared using the\n`goog.exportSymbol` and `goog.exportProperty` functions.\n\n\nMore information is available in the Closure Library documentation of\nthese functions. However, be aware they have special compiler support\nand will be totally transformed in the compiled output. \n\nIssues with Exports\n-------------------\n\n\nExports are different from externs in that they only create an exposed\n*alias* for consumers to reference. Within the compiled code, the exported\nsymbol will still be renamed. For this reason, exported symbols must be\nconstant, since reassigning them in your code would cause the exposed\nalias to point to the wrong thing.\n\n\nThis subtlety in renaming is especially complicated with respect to exported\ninstance properties.\n\n\nIn theory, exports can allow smaller code-size compared to externs, since long\nnames can still be changed to shorter ones within your code. In practice,\nthese improvements are often very minor, and don't justify the confusion exports create.\n\n\nExports also don't provide an API for consumers to follow in the way externs do.\nCompared to exports, externs document the symbols you intend to expose,\ntheir types, and give you a place to add usage information. Additionally,\nif your consumers are also using Closure Compiler, they will need externs to\ncompile against."]]