【问题标题】:Reading server environment variable in Angular at runtime在运行时读取 Angular 中的服务器环境变量
【发布时间】:2020-10-29 09:25:41
【问题描述】:

我是 Angular 的新手。我已经将一个角度应用程序部署到 aws 中的 docker 容器中。该应用程序需要连接到 aws s3 存储桶。我不需要硬编码 aws 密钥,所以我在 docker 中设置了一个环境变量。 Angular 的部署使得来自 ng 构建的 dist 文件夹由 nginx docker 容器提供服务。

一旦将 dist 文件夹中的内容提供给服务器,是否可以通过角度读取服务器环境变量?像 php 和 nodejs 中的 env 函数

【问题讨论】:

  • 你的 Angular 应用必须从 S3 获得什么?
  • @TheFabio 从客户端获取视频并将其上传到 s3。早些时候它被转换为base64并发送到api。但是由于某种原因,当视频大于 10 MB 时,php 后端无法对其进行解码。是个坏主意。
  • base64 视频编码听起来很可怕......您可以创建一个新端点来接收二进制格式的视频,作为多部分请求stackoverflow.com/questions/16958448/…。服务器中的这个端点应该将它发送到 s3 而不是你的 ng 应用程序

标签: angular docker


【解决方案1】:

不幸的是,在 Angular 中无法读取类似于 nodejs 或 Spring Boot 等服务器框架提供的机制的环境变量。

但是,您可以在 Angular 应用程序启动之前从服务器加载环境(请在采用此路径之前阅读下面的缺点)。

从服务器加载环境变量:

  • 从根模块(例如 AppModule)中删除引导组件,使其不会自动引导
  • 在 root 中创建一个加载环境变量的单例服务,例如:
import { Injectable } from "@angular/core";

@Injectable({ providedIn: "root" })
export class EnvService {
  public myEnv: string;

  fetchEnv() {
    // This has to retrieved from some server.
    return fetch("some-url").then(env => {this.myEnv = env.myEnv; return Promise.resolve("env loaded");};
  }
}
  • 延迟根模块中的引导,直到加载环境:
@NgModule({
  imports: [BrowserModule, FormsModule],
  declarations: [AppComponent, HelloComponent]
})
export class AppModule {
  constructor(private envService: EnvService) {}
  ngDoBootstrap(app) {
    this.envService.fetchEnv().then(() => app.bootstrap(AppComponent));
  }
}

这种方法有几个缺点:

  • 在加载其他环境变量之前,必须知道从中检索环境设置的 url
  • 如果无法加载环境变量,Angular 应用程序将无法启动。当您使用 Docker 时,您可以在 Docker 容器内托管一个小型 Web 服务器,该服务器在 Angular 应用程序的专用端点上提供环境变量。但是,这可能会带来一些问题,因为这会使创建 Angular Docker 容器变得更加复杂。

因此,我建议在构建期间配置环境变量。

有两种方法可以设置环境变量在构建过程中:

1) 使用自定义 webpack 配置在构建中设置环境变量

看到这个article。

您可以在 angular.json 中指定自定义 webpack 配置:

"architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "customWebpackConfig": {
              "path": "extra-webpack.config.js"
            },
...

webpack 配置文件如下所示:

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        // Here you can set your env variables.
        SERVER_URL: JSON.stringify(process.env.SERVER_URL)
      }
    })
  ]
}

这个方法需要更多的依赖:

@angular-builders/custom-webpack
dotenv

2) 在构建过程中动态创建环境文件

参见例如自动生成的 src/environments/environment.prod.ts。 您可以使用正确的环境值生成此文件,或在构建期间替换此文件中的占位符。

编辑:另见法比奥的回答。您可能不希望您的用户知道 S3 存储桶,如果可能,应该通过 Web 服务器将您的请求路由到存储桶。

【讨论】:

    【解决方案2】:

    php 和 nodejs 在服务器端运行,这就是它们可以访问服务器环境变量的原因。

    Angular 应用程序可以读取的任何内容都会暴露给客户端,因为 Angular 在浏览器中运行。我假设您不希望您的 AWS 密钥在任何用户都可以准备好的客户端上浮动。这会将您的后端暴露给恶意使用。

    如果你真的选择走这条路,你总是可以在你的 Angular 应用程序正在交谈的服务器应用程序中创建一个端点来公开服务器环境变量。

    更常见的模式是让您的服务器端点为 Angular 而不是其环境变量提供数据:

    1. 您的 Angular 服务从服务中调用一个端点;
    2. 服务器使用其配置和变量获取数据;
    3. 服务器用数据响应角度服务调用;

    我过度简化了服务器交互,因为我建议您与这个问题分开阅读。 This post 应该可以帮助您开始进行后端/前端分离。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      相关资源
      最近更新 更多