首页 > 解决方案 > _为什么_ AoT 会降低这个值?

问题描述

我有一个带有环境变量的 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 输出中,但在运行时仍然未定义?

标签: angular

解决方案


如果您查看 angular.json,您会发现这样的配置

"fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.prod.ts"
      }
    ],

女巫扔掉你的 environment.ts 并使用 environment.prod.ts 构建你的应用程序。要解决您的问题,我想您只需从配置中删除“fileReplacements”部分


推荐阅读