Angular 模块中的 window.location.origin 为空

Posted

技术标签:

【中文标题】Angular 模块中的 window.location.origin 为空【英文标题】:window.location.origin is null in Angular module 【发布时间】:2021-06-12 19:28:18 【问题描述】:

我有一个应用程序和一个库,两个独立的存储库。我的应用使用了我的库,而我的库包含一个执行 http 请求的服务。

我的应用程序部署到多个环境,我使用 Angular 的 environment.ts 文件来定义外部服务所在的位置。所有应用程序都通过网关提供服务,并位于同一个 window.location.origin。

ivy 被禁用,aot 被启用。

我的库公开了一个 forRoot,如下所示:

  declarations: [
    ToggleDirective
  ],
  providers: [
    ToggleService,
    ToggleServiceConfig
  ],
  exports: [
    ToggleDirective
  ]
)
export class ToggleModule 
  static forRoot(config: ToggleServiceConfig): ModuleWithProviders<ToggleModule> 
    return 
      ngModule: ToggleModule,
      providers: [
        provide: ToggleServiceConfig, useValue: config 
      ]
    ;
  

我的 App 的 environment.ts 如下所示:

export const environment = 
   ...
   togglesUrl: window.location.origin + '/release-toggling',
   ...
;

在我的 App 的 app.module 中,我是这样配置的:


...

const releaseToggleServiceConfig: ToggleServiceConfig = 
    togglesUrl: environment.togglesUrl
;

...

@NgModule(
    declarations: [AppComponent],
    imports: [
        CoreModule,
        SharedModule,
        ...
        ToggleModule.forRoot(releaseToggleServiceConfig)
    ],
    ...
)
export class AppModule 

如果我硬编码 window.location.origin(本地,到 'localhost:4200'),那么它工作正常。显然,现阶段还不存在窗口。这可能与 aot 有关,但不幸的是,禁用 aot 不是一个选项。

正确传递 window.location.origin 的最佳模式/实践是什么。从技术上讲,在应用程序调用我的外部服务之前不需要它。

我对您的解决方案或建议感兴趣。这可能是很容易解决的问题,许多人以前都遇到过。

【问题讨论】:

只是为了调试和确认 window.location.origin 在这一点上实际上是空的。在你的forRoot 函数中,你可以console.log(window.location.origin)console.log(config.togglesUrl) 【参考方案1】:

所有应用都通过网关提供服务,并位于同一个 window.location.origin。

如果两个应用程序都在同一个网关上,并且域也相同,那么也许您可以跳过 environment.ts 中的 window.location.origin:

export const environment = 
   ...
   togglesUrl: '/release-toggling',
   ...
;

【讨论】:

那行不通,因为如果我在example.com/deep/in/my/app,它会相对尝试这样做,而 window.location.origin 会给我网关 url (example.com)【参考方案2】:

显然问题在于该值是在编译期间解析的。您可以尝试使用 togglesUrl: () =&gt; window.location.origin 之类的函数,然后从代码中调用它。

我个人认为没有任何理由需要使用这种方法。这对您没有任何好处。如果您直接使用 my/request 之类的名称调用您的服务,这将自动解析到当前域。

另一种选择是直接在服务中解析来源,或者更好的方法是创建一个 HttpInterceptor,它会在运行时修补请求 URL。

附:您事先知道 URL,因此您可以在开始时轻松定义正确的 URL,而不是玩 Location。

【讨论】:

【参考方案3】:

我认为除了将域存储在环境中之外,您还需要使用其他东西。

一些选项:

    使用相对 URL 例如:this.http.get('/someUrl') 在这种情况下,请求是针对当前域的。 为本地使用使用代理。 Docs 在您的环境中使用静态 URL 使用location.prepareExternalUrldocs 可能是组合

【讨论】:

以上是关于Angular 模块中的 window.location.origin 为空的主要内容,如果未能解决你的问题,请参考以下文章

window.location 的各个参数

angular.module()创建获取注册angular中的模块

Angular中的核心模块组件和共享模块实现

window.location.hash

Angular:如何为 Angular 应用程序中的功能创建测试模块?

Angular2:多个模块中的一个模块实例