防止闭包编译器在不使用括号表示法的情况下重命名属性

Prevent Closure Compiler from renaming properties without using bracket notation

本文关键字:表示 情况下 属性 重命名 闭包 编译器      更新时间:2023-09-26

我正在开发一种需要有条件地向最终用户公开API的产品。我们使用闭包编译器进行缩小。我尝试公开的 API 部分是一个函数,该函数调用带有Result的回调,该的值是具有某些属性的对象。

具体来说,我尝试公开的函数看起来像这样(伪 jsdoc 表示法(:

/**
 * @type DocumentRenderResult {status: String, image?: HTMLImageElement|HTMLCanvasElement}
 * @param {function(Result<DocumentRenderResult>)} callback
**/
function renderDocument (url, page, callback) {
}

Result类如下所示:

/**
 * @template T
 * @param {Boolean} ok
 * @param {T} val
 * @param {Error} err
**/
function Result (ok, val, err) {
    this.ok = ok;
    this.val = val;
    this.err = err;
}

我想要的是公开Result对象 API - 即存在okvalerr属性的事实,并公开renderDocument接口,以便提供回调的用户能够访问statusimage属性。

一种解决方案(可能(是在任何地方使用括号表示法,但由于这应该只是有条件地公开(对于某些最终用户(,我想将其是否缩小的概念与代码分开。

我认为@implements和@export以及外部文件的组合可以做到这一点,但我还没有弄清楚。

我正在尝试做的事情可能吗?

有两种主要方法可以处理这种情况:

不带闭包库

将所有导出存储在单独的文件中,该文件将成为 api 公开库的主入口点。此方法不依赖于外部库。有关这方面的示例,请参阅我的地理位置标记库。

使用闭包库(或至少其中的一部分(

如果您愿意在项目中使用闭包库代码的一小部分,则可以使用 @export 注释。 除非指定了编译标志--generate_exports,否则@export批注不执行任何操作。

使用 --generate_exports 时,编译器将对 closure-library 的 goog.exportProperty 或 goog.exportSymbol 方法添加适当的调用。

/** @const */
var mynamespace = {};
/** @export */
mynamespace.maybeExposedMethod = function() {};

使用 --generate_exports 标志,编译器将生成代码:

var mynamespace = {maybeExposedMethod:function() {}};
goog.exportSymbol("mynamespace.maybeExposedMethod",
    mynamespace.maybeExposedMethod);

而不必依赖所有的闭包库。您可以将这 2 种方法的定义复制到源代码中。所需要的只是它们作为这些名称存在。

有条件重命名记录类型

必须区别对待返回匿名对象的函数以防止重命名。这里最好的选择是在其自己的文件中定义记录类型。要使公共 API 阻止重命名,请将记录定义作为外部包含在内。如果要重命名记录属性,请将定义作为源包括在内。

my_typedefs.js

/** @typedef {{image: string, status: number}} */
var my_record_type;

my_method_def.js

/** @return {my_record_type} */
function my_method() {
  return {
    image: 'some_image.jpg',
    status: 200
  };
}

如果 my_typedefs.js 包含在带有 --js 标志的编译中,则将重命名记录属性,但如果它包含在 --externs 标志中,则不会重命名它们。