我有一个带有环境变量的 Angular 5 项目。我一直在 environment/ 文件夹中使用一个 common.ts 文件,如下所示:
环境.prod.ts
import common from './common/common';
export const environment: any = {
... common,
production: true,
devEnvironment: false,
...
构建--prod
导致共同的值未定义(这很明显,因为来自common的environment.startupProject属性定义了应用程序路由中的默认路由),但我们发现这很奇怪,因为我们可以看到 Object.assign 在已编译的 javascript 并具有以下值:
在 main...ts 深处的某个地方
kZql: function(t, e, n) {
"use strict";
n.d(e, "a", function() {
return r
});
var r = (this && this.__assign || Object.assign || function(t) {
for (var e, n = 1, r = arguments.length; n < r; n++)
for (var i in e = arguments[n])
Object.prototype.hasOwnProperty.call(e, i) && (t[i] = e[i]);
return t
}
)({}, {
projectName: "accounts",
startupProject: "/dashboard",
...
}, {
production: !0,
devEnvironment: !1,
...
})
},
请注意,即使源映射关闭也是如此。
更新:如果我将 main.ts 修改为 console.log 相同的常见:
import common from '@src/environments/common/common';
if (environment.production) {
enableProdMode();
console.log(common);
}
它被定义了!它只是从 environment.prod 本身的上下文中才没有定义。
如果我使用调试器并打开源映射,然后在 environment.prod 中的环境对象的初始化处设置断点,我可以看到 common(或者更确切地说,它是底层 uglified 变量)实际上是未定义的。所以我猜上面的那个片段,实际上并没有执行……至少在我们的路由模块中访问环境之前没有。显然,在某处也正在生成相同代码的另一个副本,并且它正在运行该副本。坦率地说,这让我觉得 AoT 做得不是很好。
几乎就像我们的项目中实际嵌入了一些剩余的 tree-shaking,并且其行为与编译期间进行的 tree-shaking 不同。
为什么会这样?
更糟糕的是,我无法以任何通常的方式修复它:
避免导出默认值什么都不做。
将其转换为类并添加到 app-module 不起作用!:
@Injectable()
export class Common {
static startupProject = '/dashboard';
}
//... and in app.module
...
providers: [
Common,
...
//... then in environment.prod:
import { Common as common } from ...
export environment: any = {
...common, // this works without --prod, of course, but not with it
}
上述两种情况,再加上将文件夹迁移common/
到下面app/
也不起作用。
避免像... 这样的splatObject.assign({}, common, {/* ...env ...*/})
运算符也不起作用。
将值分配给(window as any).common
不起作用(这已被规定为防止角度回购中答案中的树抖动的一种方法)。...(window as any).common,
事实上,即使我也在环境中使用而不是导入的副本,这仍然不起作用!
除了关闭 AoT 之外,还有什么方法可以让它工作,这样我们就不必保留重复的信息副本?到底发生了什么——为什么该文件存在于已编译的 JS 输出中,但在运行时仍然未定义?