-
Notifications
You must be signed in to change notification settings - Fork 1k
ES6 modules and Closure Library
While Closure Library does not currently have any ES modules (formerly "ES6 modules"), the Closure Compiler and the Library's Debug Loader are compatible with ES modules.
For more information on interop see ES6 modules and Closure interop
For a migration guide from goog.module
s to ES modules, see Migrating from goog.modules to ES6 modules.
Closure Library comes equipped with a code loader in base.js
. It was originally designed to load uncompiled goog.provide
and goog.module
files in a browser. The Debug Loader needs the dependency graph of your files ahead of time, which is done with repeated calls to goog.addDependency
(see deps.js
for an example).
Even though browsers can load ES modules, if you program has any goog.require
s anywhere, you will need to make Closure Library aware of all your ES modules with goog.addDependency
calls, and include a module: 'es6'
load flag. You should not need to be writing these calls yourself. The npm package google-closure-deps
can scan your source files and write these files for you.
Additionally you should not import
your program's entry point - you will need to either goog.require
or goog.bootstrap
it. Thus it is recommended your program entry point call goog.declareModuleId
if it is an ES module, so that you have something to pass to goog.require
/ goog.bootstrap
.
Closure Library needs to know about your ES modules and load them for you (rather than allow the browser to do so) as it must load all Closure files that are goog.require
d before the goog.require
s for them are executed.
Example project:
// es6.js
// The file that defines "goog.math" must be loaded before this statement
// executes, so the Debug Loader must be made aware of this.
const math = goog.require('goog.math');
export const CONSTANT = math.sum(1, 1, 2, 3, 5, 8, 13, 21);
// entry.js
import {CONSTANT} from './es6.js';
goog.declareModuleId('entry-point');
console.log(CONSTANT);
// mydeps.js
// Notice: ES modules do not provide anything unless they call declareModuleId.
goog.addDependency('../../es6.js', [], ['goog.math'], {'lang': 'es6', 'module': 'es6'});
// Notice: Imports for ES modules end up adding require for the ES module's relative path
// from Closure Library.
goog.addDependency('../../entry.js', ['entry-point'], ['../../es6.js'], {'lang': 'es6', 'module': 'es6'});
<script src="closure/goog/base.js"></script>
<script src="mydeps.js"></script>
<script>
goog.bootstrap(['entry-point'], () => console.log('Program loaded!'));
</script>
It is important to note that, while goog.module
s may be declared to export a "legacy namespace" (via goog.module.declareLegacyNamespace()
there is no such analogue for ES modules. This means that it is impossible to goog.require
an ES module directly in a goog.provide
script (assuming you plan to use the module's exports). The exports from a goog.declareModuleId
module may only be accessed within a goog.module
and only by aliasing (or destructuring) the result of goog.require()
ing the module ID.
// es-module.js
goog.declareModuleId('esmod');
export const x = 42;
export default 'default';
// goog-module.js
goog.module('googmod');
const esmod = goog.require('esmod');
console.log(esmod.x, esmod.default);