你好,

AWS CDK 和 Amplify 应用程序的无缝集成曾经非常麻烦!使用 Amplify 前端 React 应用程序的运行时配置,现在要容易得多。在这里,我想向您介绍运行时配置的概念。

在我的全栈项目中,我经常使用 AWS CDK 作为后端。 AppSync 作为 GraphQL 实现是前端和后端之间的接口。前端通常是托管在 S3 存储桶中的 React SPA(单页应用程序)。我使用 AWS Cognito 来管理和验证用户,并且通常使用 AWS Amplify 配置前端 React 应用程序。

Idea runtime-config

runtime-config 允许您在运行时的构建阶段之后配置 Amplify。 SPA 的 dist 文件夹在 public 文件夹中提供了一个类似 runtime-config.json 的文件,该文件获取了应用程序的运行时。在这里,您可以看到 runtime-config.json 的示例:

{
  "region": "eu-central-1",
  "identityPoolId": "eu-central-1:cda9c404-0e74-439d-b40c-90204a0e1234",
  "userPoolId": "eu-central-1_Uv0E91234",
  "userPoolWebClientId": "1t6jbsr5b7utg6c9urhj51234",
  "appSyncGraphqlEndpoint": "https://wr2cf4zklfbt3pxw26bik12345.appsync-api.eu-central-1.amazonaws.com/graphql"
}

进入全屏模式 退出全屏模式

然后通过 useEffect 和 fetch 将 runtime-config 动态加载到 React 应用程序中:

useEffect(() => {
    fetch('/runtime-config.json')
      .then((response) => response.json())
      .then((runtimeContext) => {
        runtimeContext.region &&
          runtimeContext.userPoolId &&
          runtimeContext.userPoolWebClientId &&
          runtimeContext.identityPoolId &&
          Amplify.configure({
            aws_project_region: runtimeContext.region,
            aws_cognito_identity_pool_id: runtimeContext.identityPoolId,
            aws_cognito_region: runtimeContext.region,
            aws_user_pools_id: runtimeContext.userPoolId,
            aws_user_pools_web_client_id: runtimeContext.userPoolWebClientId,
            aws_appsync_graphqlEndpoint: runtimeContext.appSyncGraphqlEndpoint,
            aws_appsync_region: runtimeContext.region,
            aws_appsync_authenticationType: 'AMAZON_COGNITO_USER_POOLS',
            Auth: {
              region: runtimeContext.region,
              userPoolId: runtimeContext.userPoolId,
              userPoolWebClientId: runtimeContext.userPoolWebClientId,
              identityPoolId: runtimeContext.identityPoolId,
            },
          });
      })
      .catch((e) => console.log(e));
  }, []);

进入全屏模式 退出全屏模式

如您所见,最初执行加载 runtime-config.json 的提取。之后,使用提取的属性配置 Amplify。

您还可以使用HTML 窗口变量来设置放大参数。但是,我更喜欢这里介绍的 fetch 解决方案,因为它可能对丢失的 runtime-config.json 或单个丢失的属性更敏感。此外,应避免使用窗口变量,因为它们可以全局访问 DOM。

工作流程

没有运行时配置来构建和部署 React 应用程序的典型工作流程有时是这样的:

  • curl 并存储当前端点,例如用户池 id、AppSynch 端点等。

  • 构建放大配置文件

  • 构建反应应用

  • cdk 将 react dist 文件夹部署到 S3

使用 runtime-config 构建管道工作流:

  • 构建反应应用

  • cdk deploy react dist 文件夹和运行时配置到 S3

CDK示例

完整代码在我的GitHub Senjuns 项目中。

const userPool = new cognito.UserPool(...)
...
const identityPool = new cognito.CfnIdentityPool(...)
...

const dashboard = new StaticWebsite(this, 'dashboard', {
    build: '../dashboard/build',
    recordName: 'dashboard',
    domainName: props.domainName,
    runtimeOptions: {
        jsonPayload: {
            region: core.Stack.of(this).region,
            identityPoolId: identityPool.ref,
            userPoolId: userPool.userPoolId,
            userPoolWebClientId: userPoolWebClient.userPoolClientId,
            appSyncGraphqlEndpoint: graphqlUrl.stringValue,
        },
    },
});

进入全屏模式 退出全屏模式

StaticWebsite 是一个简单的 L3 CDK 结构,以 S3 静态网站存储桶作为主要资源。您可以在此处查看更多详细信息。但有趣的细节在 runtimeOptions 对象中。那里存储了 Amplify 的运行时配置的端点。这背后是 S3 存储桶部署构造,它通过 s3deploy.Source.jsonData(...) 将端点传输到 JSON 文件 runtime-config.json:

const DEFAULT_RUNTIME_CONFIG_FILENAME = 'runtime-config.json';

...

new s3deploy.BucketDeployment(this, 'BucketDeployment', {
    sources: [
    s3deploy.Source.asset(props.build),
    ...(props.runtimeOptions
        ? [
        s3deploy.Source.jsonData(
            props.runtimeOptions?.jsonFileName ||
                DEFAULT_RUNTIME_CONFIG_FILENAME,
            props.runtimeOptions?.jsonPayload,
        ),
        ]
        : []),
    ],
    distribution,
    destinationBucket: siteBucket,
});

进入全屏模式 退出全屏模式

这是一个很酷的 CDK 集成 :) !只给 BucketDeployment Construct 两个参数,比如 React dist 和 runtime-config 是一个非常聪明的主意。

嵌套堆栈输出的解决方法

在我使用 runtime-config 的过程中,我遇到了一个问题。无法将嵌套堆栈中的 CDK 输出用于运行时配置。但是有一个使用 AWS Systems Manager 参数的解决方法:

const graphqlUrl = new ssm.StringParameter(this, 'GraphqlUrl', {
    parameterName: 'GraphqlUrl',
    stringValue: appSyncTransformer.appsyncAPI.graphqlUrl,
});

...

const dashboard = new StaticWebsite(this, 'dashboard', {
    build: '../dashboard/build',
    recordName: 'dashboard',
    domainName: props.domainName,
    runtimeOptions: {
    jsonPayload: {
        region: core.Stack.of(this).region,
        identityPoolId: identityPool.ref,
        userPoolId: userPool.userPoolId,
        userPoolWebClientId: userPoolWebClient.userPoolClientId,
        appSyncGraphqlEndpoint: graphqlUrl.stringValue,
    },
    },
});

进入全屏模式 退出全屏模式

很酷,对吧?嵌套堆栈输出只是存储在 SSM 字符串参数中,然后可以稍后读取。感谢 Adrian Dimech 出色的解决方法🙏。

结论

AWS CDK 和 Amplify 是一个强大的组合。使用此处提供的运行时配置,这种组合感觉好多了!我从aws-prototyping-sdk复制了这个解决方案。此存储库中正在开发一些有趣的 AWS CDK 结构。所以你一定要检查一下!

感谢DeepL 翻译器(免费版)帮助翻译成英文并为我节省了大量时间:)。

我喜欢从事开源项目。我的很多东西你已经可以在https://github.com/mmuller88上使用。如果您喜欢我在那里的工作和我的博客文章,请考虑支持我:

给我买一台 Ko-Fi

或者

给我买一台 Ko-Fi

别忘了访问我的网站

martinmueller.dev

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐