Externes et exportations
Restez organisé à l'aide des collections
Enregistrez et classez les contenus selon vos préférences.
Objectif des externes
Les externs sont des déclarations qui indiquent au compilateur Closure les noms des symboles qui ne doivent pas être renommés lors de la compilation avancée.
Ils sont appelés "externes" car ces symboles sont le plus souvent définis par du code en dehors de la compilation, tel que du code natif ou des bibliothèques tierces. Pour cette raison, les fichiers externes comportent souvent des annotations de type, afin que Closure Compiler puisse vérifier le type de votre utilisation de ces symboles.
En général, il est préférable de considérer les fichiers externes comme un contrat d'API entre l'implémenteur et les consommateurs d'un code compilé. Les externs définissent ce que l'implémenteur s'engage à fournir et ce sur quoi les consommateurs peuvent s'appuyer. Les deux parties doivent disposer d'une copie du contrat.
Les externs sont semblables aux fichiers d'en-tête dans d'autres langages.
Syntaxe des externs
Les fichiers externes ressemblent beaucoup à des fichiers JavaScript normaux annotés pour Closure Compiler. La principale différence est que leur contenu n'est jamais imprimé dans la sortie compilée. Par conséquent, aucune des valeurs n'a de sens, seuls les noms et les types en ont.
Vous trouverez ci-dessous un exemple de fichier externs pour une bibliothèque simple.
// 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) {};
Option --externs
En général, l'annotation @externs
est le meilleur moyen d'indiquer au compilateur qu'un fichier contient des externs. Ces fichiers peuvent être inclus en tant que fichiers sources normaux à l'aide de l'indicateur de ligne de commande --js
.
Toutefois, il existe une autre méthode plus ancienne pour spécifier les fichiers externes. L'option de ligne de commande --externs
peut être utilisée pour transmettre explicitement les fichiers externs. Cette méthode n'est pas recommandée.
Utiliser des externes
Les externs ci-dessus peuvent être utilisés comme suit.
/**
* @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;
}
Objectif des exportations
Les exportations sont un autre mécanisme permettant d'attribuer des noms cohérents aux symboles après la compilation. Elles sont moins utiles que les externs et souvent déroutantes. Il est préférable de les éviter dans tous les cas, sauf les plus simples.
Les exportations reposent sur le fait que Closure Compiler ne modifie pas les littéraux de chaîne.
En attribuant un objet à une propriété nommée à l'aide d'un littéral, l'objet sera disponible via ce nom de propriété, même après la compilation.
Vous trouverez ci-dessous un exemple simple.
/**
* @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;
Si vous utilisez la bibliothèque Closure, les exportations peuvent également être déclarées à l'aide des fonctions goog.exportSymbol
et goog.exportProperty
.
Pour en savoir plus, consultez la documentation de la bibliothèque Closure sur ces fonctions. Toutefois, sachez qu'ils bénéficient d'une prise en charge spéciale du compilateur et qu'ils seront totalement transformés dans le résultat compilé.
Problèmes liés aux exportations
Les exportations diffèrent des externs en ce qu'elles ne créent qu'un alias exposé que les consommateurs peuvent référencer. Dans le code compilé, le symbole exporté sera toujours renommé. C'est pourquoi les symboles exportés doivent être constants, car leur réaffectation dans votre code entraînerait la redirection de l'alias exposé vers le mauvais élément.
Cette subtilité de la modification du nom est particulièrement complexe en ce qui concerne les propriétés d'instance exportées.
En théorie, les exportations peuvent permettre une taille de code plus petite que les externs, car les noms longs peuvent toujours être remplacés par des noms plus courts dans votre code. En pratique, ces améliorations sont souvent très mineures et ne justifient pas la confusion que créent les exportations.
Les exportations ne fournissent pas non plus d'API à suivre pour les consommateurs, contrairement aux externs. Par rapport aux exportations, les externs documentent les symboles que vous souhaitez exposer, leurs types et vous permettent d'ajouter des informations sur leur utilisation. De plus, si vos consommateurs utilisent également Closure Compiler, ils auront besoin d'externs pour la compilation.
Sauf indication contraire, le contenu de cette page est régi par une licence Creative Commons Attribution 4.0, et les échantillons de code sont régis par une licence Apache 2.0. Pour en savoir plus, consultez les Règles du site Google Developers. Java est une marque déposée d'Oracle et/ou de ses sociétés affiliées.
Dernière mise à jour le 2025/07/26 (UTC).
[[["Facile à comprendre","easyToUnderstand","thumb-up"],["J'ai pu résoudre mon problème","solvedMyProblem","thumb-up"],["Autre","otherUp","thumb-up"]],[["Il n'y a pas l'information dont j'ai besoin","missingTheInformationINeed","thumb-down"],["Trop compliqué/Trop d'étapes","tooComplicatedTooManySteps","thumb-down"],["Obsolète","outOfDate","thumb-down"],["Problème de traduction","translationIssue","thumb-down"],["Mauvais exemple/Erreur de code","samplesCodeIssue","thumb-down"],["Autre","otherDown","thumb-down"]],["Dernière mise à jour le 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."]]