在带有属性的ES6模块上使用Closure Compiler

时间:2017-12-29 14:14:24

标签: javascript ecmascript-6 gulp google-closure-compiler es6-modules

经过一天的测试后,我几乎就在那里:使用google-closure-compiler-jsgulp.js来缩小/编译基于“库”的ES6模块。

只剩下一个问题了。如何调用导入模块的属性?

我的测试用例包含3个文件:

gulpfile.js

const gulp = require("gulp");
const compiler = require("google-closure-compiler-js").gulp();
const sourcemaps = require("gulp-sourcemaps");

gulp.task("default", function() {
// wildcards don't seem to work yet with the js version
// files need to be in reverse order of dependency...
return gulp.src(["src/boilerplate/main.js", "src/app.js"])
    .pipe(sourcemaps.init())
    .pipe(compiler({
        jsOutputFile: "app.min.js",
        compilationLevel: "ADVANCED",
        warningLevel: "VERBOSE",
        createSourceMap: true
    }))
    .pipe(sourcemaps.write("/"))
    .pipe(gulp.dest("./dist"));
});

src/boilerplate/main.js

var mod = {};
export default mod;

var foo = "FOO";
var bar = "BAR";

function foobar(join) {
    join = (typeof join === "string") ? join : "";
    return foo + join + bar;
}
Object.defineProperty(mod, "foobar", {value: foobar});

src/app.js

import boilerplate from "./boilerplate/main.js";

console.log(boilerplate["foobar"]("+"));
console.log(boilerplate.foobar("+"));

如果您在此处记录boilerplate,则会看到它具有“foobar”属性。符号完整和所有。太好了!

因此,app.js的第一个调用 - 括号表示法[“foobar”] - 完美无缺。但是,点符号没有。 Closure Compiler缩小了对导入模块属性的调用! 你得到了经典的“嗨。我是ADVANCED模式的新手”错误:TypeError: a.a is not a function

如何防止这种情况? (& let假设直接输出foobar是不可行的,为了现实世界的缘故。)

  • 我是否需要导出文件?我到底该怎么做?我在那个方向上的第一次冒险并没有把我带走......是否有google-closure-compiler-js特有的技巧?

  • 在Closure Compiler添加一项自动不重命名对导入属性的调用的功能之前,是否存在某种允许使用点符号的黑客攻击?

  • 这篇closure-compiler/wiki关于 JS-Modules#type-references 的文章建议我做些什么?这是我未能实现的答案吗?

    /** @param {foo.Foo} Foo */ function(Foo) {}

1 个答案:

答案 0 :(得分:1)

对于ADVANCED模式兼容性,请使用Object.defineProperties以避免引用字符串。

Object.defineProperties(mod, {
  foobar: {value: foobar}
});

无论何时使用带引号的字符串,您都需要使用括号(或其他技术)或冒险违反一致的属性访问规则。