[Code翻译]在VS Code配置Flutter的App环境变量应用

570 阅读4分钟

本文由 简悦SimpRead 转码,原文地址 medium.com

在不同的应用环境中运行你的Flutter应用

image.png (图片来源。xtreemsolution.com/blog/user-a…

什么环境?

在我处理的每一个项目中,我们使用多个环境来分离部署是非常重要的。

通常,我们有四个环境。

  • DEV是由开发人员使用的。测试不应该在这个环境中进行,因为它总是在变化。
  • QA将由你的测试人员使用,以确保软件没有错误。
  • UAT确保你的软件在你的目标用户手中能按预期工作。
  • PROD包含你的软件的最新版本,它通过了所有的测试,并普遍提供给你的目标用户。

从开发者的角度来看,不同的环境可能意味着你的软件的不同配置。这些可能包括敏感的应用程序秘密,如API密钥,或不同的应用程序风味。

管理它们都

我们可以为每个环境准备不同的配置或秘密文件,并在整个开发团队中共享。这些文件不应该在我们的存储库中提交

创建你的秘密文件。这些文件的格式应该是JSON文件。 下面是每个环境的样本秘密文件。我们将提取这些值,并在构建过程中作为Dart Defines传递给他们。

{
    "appTitle": "Sample App (DEV)",
    "appServerUrl": "https://my-sample-app-server-dev.com/api",
    "appServerApiKey": "OwAFIpleinPv5S592PUZzGwMYvirC4EFeBcvlbcGPeDfLTL12Rnmo3kV18m1hLXQSXi6MgLSsYmGg",
    "myOtherSecret": "my other secret value for DEV"
}

(DEVS的样本秘密文件)

{
    "appTitle": "Sample App (QA)",
    "appServerUrl": "https://my-sample-app-server-qa.com/api",
    "appServerApiKey": "lbcGPeDfLTL12Rnmo3kV18m1hLXQSXi6MgLSsYmGgOwAFIpleinPv5S592PUZzGwMYvirC4EFeBcv",
    "myOtherSecret": "my other secret value for QA"
}

(QAS的样本秘密文件)

{
    "appTitle": "Sample App (UAT)",
    "appServerUrl": "https://my-sample-app-server-uat.com/api",
    "appServerApiKey": "gOwAFIpleinPv5S592PUZzGwMYvirC4lbcGPeDfLTL12Rnmo3kV18m1hLXQSXi6MgLSsYmGEFeBcv",
    "myOtherSecret": "my other secret value for UAT"
}

(UAT的样本秘密文件)

{
    "appTitle": "Sample App",
    "appServerUrl": "https://my-sample-app-server.com/api",
    "appServerApiKey": "TL12Rnmo3kV18m1hLXQSXi6MgLSsYmGgOwAFIpleinPv5S592PUZzGwMYvirC4EFeBcvlbcGPeDfL",
    "myOtherSecret": "my other secret value for PROD"
}

(PROD的样本秘密文件)

将你的秘密文件放在项目目录下一个名为.env的新文件夹中。在你的".gitignore "中添加这个文件夹和文件名模式*.secrets

image.png (记住不要提交这些文件!)

为了在运行项目时读取这些文件,请安装Command Variable作为VS Code的一个扩展。

image.png (安装这个)

然后我们需要更新我们的启动配置。创建一个名为launch.json的文件并将其放在.vscode文件夹内。我们应该把这个文件夹提交到我们的存储库中。

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Run Current Device",
            "program": "lib/main.dart",
            "request": "launch",
            "type": "dart",
            "args": [
                "--dart-define",
                "appTitle=${input:appTitle}",
                "--dart-define",
                "appServerUrl=${input:appServerUrl}",
                "--dart-define",
                "appServerApiKey=${input:appServerApiKey}",
                "--dart-define",
                "myOtherSecret=${input:myOtherSecret}",
            ]
        },
    ],
    "inputs": [
        {
            "id": "appTitle",
            "type": "command",
            "command": "extension.commandvariable.file.content",
            "args": {
                "fileName": "${pickFile:config}",
                "json": "content.appTitle",
                "pickFile": {
                    "config": {
                        "description": "Select the environment to debug",
                        "include": ".env/*.secrets",
                        "keyRemember": "secretsFile"
                    }
                }
            }
        },
        {
            "id": "appServerUrl",
            "type": "command",
            "command": "extension.commandvariable.file.content",
            "args": {
                "fileName": "${remember:secretsFile}",
                "json": "content.appServerUrl"
            }
        },
        {
            "id": "appServerApiKey",
            "type": "command",
            "command": "extension.commandvariable.file.content",
            "args": {
                "fileName": "${remember:secretsFile}",
                "json": "content.appServerApiKey"
            }
        },
        {
            "id": "myOtherSecret",
            "type": "command",
            "command": "extension.commandvariable.file.content",
            "args": {
                "fileName": "${remember:secretsFile}",
                "json": "content.myOtherSecret"
            }
        },
    ]
}

运行时,VS Code会要求你选择一个文件(也就是环境),我们的秘密将从中提取并作为Dart Defines传递。所有在".env "文件夹下以".secrets "结尾的文件将被显示出来。

image.png (选择你的环境)

现在我们把这些值作为Dart Defines来传递,我们在代码中从环境中检索它们。

abstract class EnvironmentVariables {
  static const appTitle = String.fromEnvironment('appTitle');
  static const appServerUrl = String.fromEnvironment('appServerUrl');
  static const appServerApiKey = String.fromEnvironment('appServerApiKey');
  static const myOtherSecret = String.fromEnvironment('myOtherSecret');
}

(检索值)

import 'package:flutter/material.dart';
import 'package:sample_app/environment_variables.dart';

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: EnvironmentVariables.appTitle,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: EnvironmentVariables.appTitle),
    );
  }
}

(像这样使用它们)

我们现在可以在我们的应用程序中使用我们的秘密值了! 你可以在GitHub中找到这个示例应用程序。。

image.png (我们的应用程序使用DEV环境运行)

其他集成项目

Dart定义不仅可以在Dart代码中访问,也可以在平台中访问。如果我们想在平台上有不同的配置,如谷歌API密钥,这很有用。或者不同的口味,如应用后缀ID,应用名称等。

阅读更多关于它的信息这里。特别感谢Denis Beketsky的文章。

我们也可以在我们的CI/CD工作流程中使用它,创建一个脚本,将秘密文件读成JSON并提取值。

对于那些使用Windows的人来说,重要的信息是

当你的秘密文件中有长的值时,你在使用Windows开发时可能会遇到构建问题,因为操作系统在运行命令时只允许8191个字符。我已经提交了一个问题,希望Flutter团队能找到一个解决方案。


www.deepl.com 翻译