本文由 简悦SimpRead 转码,原文地址 medium.com
在不同的应用环境中运行你的Flutter应用
(图片来源。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。
(记住不要提交这些文件!)
为了在运行项目时读取这些文件,请安装Command Variable作为VS Code的一个扩展。
(安装这个)
然后我们需要更新我们的启动配置。创建一个名为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 "结尾的文件将被显示出来。
(选择你的环境)
现在我们把这些值作为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中找到这个示例应用程序。。
(我们的应用程序使用DEV环境运行)
其他集成项目
Dart定义不仅可以在Dart代码中访问,也可以在平台中访问。如果我们想在平台上有不同的配置,如谷歌API密钥,这很有用。或者不同的口味,如应用后缀ID,应用名称等。
阅读更多关于它的信息这里。特别感谢Denis Beketsky的文章。
我们也可以在我们的CI/CD工作流程中使用它,创建一个脚本,将秘密文件读成JSON并提取值。
对于那些使用Windows的人来说,重要的信息是
当你的秘密文件中有长的值时,你在使用Windows开发时可能会遇到构建问题,因为操作系统在运行命令时只允许8191个字符。我已经提交了一个问题,希望Flutter团队能找到一个解决方案。