VueJS - 我如何设计一个可以处理多个 .env 文件的项目

VueJS - How do I design a project that can handle multiple .env file

当前架构

所以,我有一个大型 vue 项目,为来自多个子域的多种类型的用户提供服务。 我通过 netlify 维护项目并将特定的 git 分支指向特定的子域。

我们称它们为 Site OneSite TwoSite Three。我有三个独立的 git 分支来控制它们,例如 mainminimicro 分支。

每个 subdomain/sites 或分支机构根据目标用户打开或关闭不同的功能。

直到现在,我都是通过一个单独的 settings.json 文件来控制它们的。通过分支到不同的分支,我单独提交更新 settings.json 以实现每个站点的行为。 (虽然现在不认为这是个好主意)

这里有一个关于 settings.json 的粗略概念(分支因分支而异):

{
  available_products: ['one', 'two', 'three'],
  feature_one_enabled: false,
  product_journey: 'ZIPPED'
  .....
  mini_mode: true,
}
// and many more flags;

缺陷

痛点来了,当我发现一个存在于所有分支中并需要在所有分支中修复的错误时,我不能只是将一个分支合并到另一个分支中,因为还有针对其他分支的其他更改.

此外,传入的功能大部分时间都是独一无二的,当前的功能会定期更改。

问题 1:保留配置标志以打开或关闭 .json 文件中的功能是一种好习惯吗? 或者我应该使用 .env 个文件。

现在怎么办

所以我尝试修复分支建模并保持代码库始终唯一,检查配置设置属性以根据分支或 settings.json 启用功能 .env 文件。

遵循 this 分支模型 btw。

因此,分支和保持每个分支中的代码库相同就解决了。这是配置的事情。我可以提供不同的 .env 值来 netlify 来控制功能和所有。

但是当我做本地开发时会变得有点麻烦,因为我必须为每个分支设置两个.env文件(total 6 for { n = 3 branches * 2 modes })

问题 2:如何将所有 .env 文件保存在本地并通过某些 npm 命令或分支更改自动更改它们?

或者我是否必须对当前架构进行一些更改?

所以,答案是给那些偶然发现这个问题并想知道我是否能解决这个问题的人的。

我可以通过修改一些 vue-cli 和 webpack 配置,借助自制插件和其他一些帮助脚本文件来解决这个问题。

从这个 thread 讨论是否有可能 异步 (接下来)将一些数据传递到 运行 之前的 webpack 配置的概念启用 npm 服务器。

关键解决方案是使用 chainWebpack 修改配置。

为什么异步

就像我说的,为了让本地开发无痛,我想根据我当前的 git 分支使用 .env 文件。但是默认命令不应更改,我不需要额外的命令。

让代码

我使用 dotenv-webpack 设置我的 .env 文件并将文件从根 / 目录移动到名为 /env

的子目录
/node_modules
/src
/public
/tests
/env // <- this

Having them in the root directory was messing up the priority of webpack deciding the *.local files despite of passing different directory to the config

现在该目录包含如下文件:

.env.branch-one
.env.branch-two
.env.branch-three
.env.branch-four
...

因为我想要一个命令来完成这一切,我添加了一个本地插件并将我的命令注册到 npm 脚本。所以在我的 devDependenciespackage.json 我添加了这个:

"vue-cli-plugin-dynamic-env": "file:src/plugins/vue-cli-plugin-dynamic-env",

并更新了当前的 run serve 命令:

"scripts": {
  ...
  "serve": "vue-cli-service serve:auto",
  ...
},

这是插件结构(在 /src/plugins/vue-cli-plugin-dynamic-env 中):

index.js // defines the plugin
generator.js // didn't do much here since it's only local plugin
getCurrentBranchName.js // helper for getting branch name
package.json

现在在 index.js 文件中,我可以在 chainWebpack 的帮助下导入并使用 dotenv-webpack 传递自定义环境文件,并且我可以使用我的帮助脚本来获取当前 git 分支生成分支名称。

然后注册一个新命令 serve:auto 之前添加到 package.json 并且在命令定义的末尾,我可以以编程方式 运行 内置的 vue-cli 服务命令。

外观如下: :

const Dotenv = require('dotenv-webpack');
const activeGitBranch = require('./getCurrentBranchName');

module.exports = (api) => {
  api.registerCommand('serve:auto', async (args) => {
    const branchName = await activeGitBranch(); // getting async value here
    api.chainWebpack((config) => {
      config.plugin('env').use(Dotenv, [{
        // fallback to default file if branch name does'nt match a .env file
        path: branchName ? `./env/.env.${branchName}` : './env/.env', 
        safe: false,
      }]);
    });
    await api.service.run('serve', args); // programmatic call to serve command
  });
};

module.exports.defaultModes = {
  'serve:auto': 'development', // setting default env mode, this is requried.
};

如果您想知道 getCurrentBranchName.js 文件的作用和方式。这是:

const { exec } = require('child_process');

module.exports = function currentBranchName() {
  return new Promise((resolve, reject) => {
    exec('git rev-parse --abbrev-ref HEAD', (error, stdout, stderr) => {
      // console.log(branchName);
      if (error) { // handle your error
        if (error.code === 128) {
          reject(error);
        }
      }
      if (stderr) {
        reject(stderr);
      }
      resolve(stdout.trim());
    });
  });
};

就是这样。

干杯