Closure-compiler: Support ES6 modules in minimally-compiled bundles

Created on 10 Sep 2017  路  5Comments  路  Source: google/closure-compiler

Feature request: it seems possible that ES6 modules would work in minimally compiled bundles (e.g. compile=False js_binary rules) by converting them to goog.module form. Something like:

// foo.js
import {bar} from './bar.js';

export const foo = bar + 10;

might be transformed to:

// bundle.js
goog.loadModule('module$foo', function() {
  const {bar} = goog.require('$module$bar');

  exports.foo = bar + 10;
});
ES6 Modules

Most helpful comment

Already working on this! Note that goog.loadModule accepts one argument currently; the module definition function. We're planning on adding a second argument, the path of the module. And we're planning on support for relative, path goog.requires in a goog.module that resolve against the path that was passed in as the argument. Mostly this is for interop between goog and ES6 modules, but it makes this bundled case nice as well.

So your above example would be transformed to

goog.loadModule(function() {
  const {bar} = goog.require('./bar.js');

  exports.foo = bar + 10;
}, '/foo.js');

bar.js would also be similarly transformed and its exports would be registered under its path (/bar.js). So when the goog.require('./bar.js') is called, it resolves to /bar.js, and the exports can be retrieved.

This will be done path based rather than symbol based since we need a similar mechanism for the debug loading case, and this way we don't need to rewrite any paths at all (either to full paths or substitutes for symbols), which would require unnecessary rewriting of goog modules in the debug loading case.

All 5 comments

Already working on this! Note that goog.loadModule accepts one argument currently; the module definition function. We're planning on adding a second argument, the path of the module. And we're planning on support for relative, path goog.requires in a goog.module that resolve against the path that was passed in as the argument. Mostly this is for interop between goog and ES6 modules, but it makes this bundled case nice as well.

So your above example would be transformed to

goog.loadModule(function() {
  const {bar} = goog.require('./bar.js');

  exports.foo = bar + 10;
}, '/foo.js');

bar.js would also be similarly transformed and its exports would be registered under its path (/bar.js). So when the goog.require('./bar.js') is called, it resolves to /bar.js, and the exports can be retrieved.

This will be done path based rather than symbol based since we need a similar mechanism for the debug loading case, and this way we don't need to rewrite any paths at all (either to full paths or substitutes for symbols), which would require unnecessary rewriting of goog modules in the debug loading case.

Hi @jplaisted -- any updates on this feature?

I think this can now be marked as a duplicate.

There's been a lot design churn here even recently. We're not going to go to goog.modules, too many issues (requires a dependency on Closure Library that wasn't there before, no support for circular dependencies, no support for future dynamic / late loading with import()).

Worth noting that there's three real cases here:

  • WHITESPACE_ONLY - this is supported today, but there's no interop with Closure files. You can compile an input of only ES6 modules in this mode and get valid output. CommonJS does have interop with ES6 modules.
  • ClosureBundler - this is what @rictic was talking about. ES6 modules are in no way supported today.
  • Closure Library debug loader transpiler.

We're going to wrap modules with the latter two cases and leave the first alone. Though we'll add interop with ES6 modules / Closure files in all three cases. Not going to add CommonJS interop with ES6 modules just yet with the latter two cases since that doesn't currently exist and doesn't appear that anyone is really asking for it.

Duplicate of #2658

Duplicate of #2658

Support for this landed awhile ago.

Was this page helpful?
0 / 5 - 0 ratings