-
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.
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())
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 module
field of the package.json file. Thus it's a good idea to publish the module also with the build for the compiler to include the source code of the package in another package being built.