-
Notifications
You must be signed in to change notification settings - Fork 0
Babel Modules
Since Compilerv20190709
, the modules imports from Babel have been working semi-correctly, because although it is possible to compile a Babel-transpiled module with Closure Compiler, the compatibility between the two is not ensured for default exports.
The following source code is used in the example on this page.
Source (@a-la/fixture-babel) |
---|
/**
* A function that returns `erte`.
*/
const erte = () => {
return 'erte'
}
/**
* A function that returns `c`.
* @param {string} input
*/
export const c = (input) => {
return 'c' + (input ? `-${input}` : '')
}
/**
* A function that returns `b`.
* @param {number} times
*/
export const b = (times) => {
return 'b' + (times ? `-${times}` : '')
}
export default erte |
Babel-compiled |
Show Code"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.b = exports.c = void 0;
/**
* A function that returns `erte`.
*/
const erte = () => {
return 'erte';
};
/**
* A function that returns `c`.
* @param {string} input
*/
const c = input => {
return 'c' + (input ? `-${input}` : '');
};
/**
* A function that returns `b`.
* @param {number} times
*/
exports.c = c;
const b = times => {
return 'b' + (times ? `-${times}` : '');
};
exports.b = b;
var _default = erte;
exports.default = _default; |
Because of how CommonJS Compatibility is implemented, all RequireJS modules will only make accessible a single default object, without named exports.
The script to import Babel-compiled modules in ES6 Code is now: | |
---|---|
import erte from '@fixture/babel'
console.log(erte.default())
console.log(erte.c(''))
console.log(erte.b('')) |
|
Although it's impossible to use such code with Babel runtime, the code above can be compiled using Google Closure Compiler.
Command & Warnings | |
---|---|
java -jar /Users/zavr/node_modules/google-closure-compiler-java/compiler.jar \
--compilation_level ADVANCED --language_out ECMASCRIPT_2017 --formatting \
PRETTY_PRINT --process_common_js_modules --package_json_entry_names module,main \
--entry_point e/b.js --externs ../externs/v8/global.js --externs \
../externs/v8/global/buffer.js --externs ../externs/v8/nodejs.js
Modules: b/i.js
b/i.js:6: WARNING - [JSC_TYPE_MISMATCH] assignment to property b of module$b$i.default
found : undefined
required: function(?): ?
exports.default = exports.b = exports.c = void 0;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
b/i.js:6: WARNING - [JSC_TYPE_MISMATCH] assignment to property c of module$b$i.default
found : undefined
required: function(string): ?
exports.default = exports.b = exports.c = void 0;
^^^^^^^^^^^^^^^^^^
0 error(s), 2 warning(s), 94.4% typed
| |
The command generates some warnings, but no errors. |
The generated code and output | |
---|---|
'use strict';
var a = {};
Object.defineProperty(a, "__esModule", {value:!0});
a.default = a.a = a.b = void 0;
a.b = b => "c" + (b ? `-${b}` : "");
a.a = b => "b" + (b ? `-${b}` : "");
a.default = () => "erte";
console.log(a.default());
console.log(a.b(""));
console.log(a.a("")); |
erte
c
b |
Trying to execute the output produces the correct result. OK, but what happens when we actually try to execute such program with @babel/register ? This is needed for testing and development. | |
MacBook:fixture-babel zavr$ node erte
erte/erte.js:7
console.log(_build.default.default());
^
TypeError: _build.default.default is not a function
at Object.<anonymous> (erte/erte.js:3:13)
at Module._compile (module.js:653:30)
at Module._compile (pirates/index.js:99:24)
at Module._extensions..js (module.js:664:10)
at Object.newLoader [as .js] (pirates/index.js:104:7)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12)
at Function.Module._load (module.js:498:3)
at Module.require (module.js:597:17)
at require (internal/module.js:11:18) |
Conclusion
|
Because of referring to the default import as .default , the compatibility with Babel is broken for default imports. Therefore, it's better to use ÀLaMode for transpilation which is compatible with Closure Compiler. |
To see what happens when trying to import { named }
exports, refer to the example below.
import erte, { c, b } from '@fixture/babel'
console.log(erte())
console.log(c())
console.log(b())
Command & Generated JS |
---|
|
depack e/1 -c -a -p --process_common_js_modules
stderr
|
Exit code 2
e/1.js:1: ERROR - [JSC_DOES_NOT_HAVE_EXPORT] Requested module does not have an export "b".
import erte, { c, b } from '../b/i'
^
e/1.js:1: ERROR - [JSC_DOES_NOT_HAVE_EXPORT] Requested module does not have an export "c".
import erte, { c, b } from '../b/i'
^
2 error(s), 0 warning(s) |
stdout
The named import syntax on CommonJS modules is not supported unless there is an ECMA6 version of the script which will be detected by static analysis in the |