【问题标题】:Vue CLI - Keep config file as external after compilationVue CLI - 编译后将配置文件保留为外部
【发布时间】:2019-05-29 00:11:19
【问题描述】:

我正在使用 Vue CLI 开发一个应用程序。 此应用程序是一个 Web 界面,必须与板上的 Rest API 进行通信。

所以,因为板子会移动,板子的 IP 会随着时间的推移而变化,这取决于我在哪里。

这是我的项目当前树:

IP 配置包含在 Settings.js 文件中:

export const Settings = {
    // Server configuration
    SERVER_IP: '127.0.0.1',
    SERVER_PORT: '9000',

    SERVER_PROTOCOL: 'http', // http or https

    // Website configuration
    DEBUG_MODE: true
};

在我的文件中,我使用以下语句导入此 IP:

import {Settings} from '../../Settings'
const ip = Settings.SERVER_IP;

// Do stuff

这很好用。但问题是:当 IP 发生变化时,我必须重新编译所有内容。因为Settings.js是和其他JS文件一起编译的。

所以,我想知道是否有办法让配置文件保留在 dist/ 目录中,并在执行期间由我的 JS 应用程序读取。所以我不必在每次我的应用服务器 IP 更改时重新编译所有内容。

你的帮助:)

【问题讨论】:

    标签: vue.js webpack vuejs2 vue-cli vue-cli-3


    【解决方案1】:

    我对 Vue 的解决方案是基于solution for Angular

    您可以拥有与后端开发人员完全相同的环境变量。

    但不同之处在于后端代码在服务器内部执行,而前端代码只不过是磁盘上的文件,您将其作为静态文件撤回,甚至没有机会在撤回之前运行和检查环境变量。

    但是您的代码正在浏览器中执行。所以这是拥有环境的理想和唯一合适的地方。

    但是,您必须事先准备好这个环境 - 根据您的后端环境。

    计划如下:

    1. 您从编译中排除您的设置文件(见下文)。
    2. 您的设置文件会在您运行 Vue 应用程序之前“构建”环境。
    3. 从您的代码中,您可以使用该环境,并且您还可以在运行时更新该环境。

    这是你的最终代码结构:

    root_project_dir:
    ├─> cfg
    │   └── settings.js
    ├─> public
    │   ├── favicon.ico
    │   └── index.html
    ├─> src
    │   ├── App.vue
    │   ├─> assets
    │   │   └── logo.png
    │   ├─> components
    │   ├─> layouts
    │   ├── main.js
    │   ├─> plugins
    │   ├─> router
    │   ├─> store
    │   └─> views
    └── vue.config.js
    

    创建设置文件cfg/settings.js:

    /*
    This file goes as an asset without any of compilation even after build process.
    Thus, it can be replaced in a runtime by different file in another environment.
    
    Example for Docker:
      docker run -v ./local_cfg_dir:cfg image:tag
    */
    
    (function(window) {
      window.__env = window.__env || {};
    
      window.__env.api = {
        "url": "http://127.0.0.1:8000",
        "timeout": 80000
      };
      window.__env.captcha = {
        "enabled": true,
        "key": "Mee1ieth1IeR8aezeiwi0cai8quahy"
      };
      window.__env.rollbar = {
        "enabled": true,
        "token": "zieriu1Saip5Soiquie6zoo7shae0o"
      };
      window.__env.debug = true;
    })(this);
    

    vue.config.jsnpm run build 阶段为Webpack Copy plugin 提供复制cfg 文件的指令(您不能更改此名称):

    module.exports = {
      chainWebpack: config => {
        config.plugin("copy").tap(([pathConfigs]) => {
          pathConfigs.unshift({
            from: "cfg",
            to: "cfg"
          });
          return [pathConfigs]})
      },
      transpileDependencies: ["vuetify"]
    };
    

    检查生成的 webpack 配置并发现它已被应用(在输出的底部):

    vue inspect
    

    现在,当您构建项目时,您将在生成的目录中看到它:

    dist
     ├─> cfg
     │   └── settings.js
     ├─> css
     │   ├── app.06b1fea6.css
     │   └── chunk-1f2efba6.a298b841.css
     ├── favicon.ico
     ├─> img
     │   └── logo.09e0e4e1.png
     ├── index.html
     └─> js
         ├── app.8fc75c19.js
         ├── app.8fc75c19.js.map
         └── chunk-vendors.1ab49693.js.map
    

    因此,您可以在 public/index.html 中运行此设置,然后在同一窗口中运行应用程序:

      <body>
        <script src="/cfg/settings.js"></script>
        <div id="app"></div>
        <!-- built files will be auto injected -->
      </body>
    

    现在你的窗口中有它了:

    您可以从代码中的任何位置访问此环境:

    Vue.use(VueReCaptcha, { siteKey: window.__env.captcha.key })
    

    旁注

    如果您想“与 DevOps 兼容”,您需要在嵌套目录中进行设置(在我们的示例中为 cfg)。这将提供在 Kubernetes/Swarm 中进行挂载而不覆盖整个 dist 目录的能力。

    【讨论】:

    • 感谢您的指导。我没有让它正常工作,因为最后一步“从代码中的任何地方你可以到达这个环境”不起作用。我在 VSCode 中收到“属性 '__env' 在类型 'Window & typeof globalThis' 上不存在”的错误。我正在开发的应用程序是打字稿。
    • @kumaheiyama 但它真的存在吗?你能像上图一样在控制台中看到 window.__env 吗?
    • 是的,我可以在控制台中看到 window.__env。难道这个解决方案不能很好地与打字稿配合使用吗?尽管使用了您的部分解决方案,但我找到了另一种解决方案。将在单独的答案中发布。
    • @kumaheiyama 如果您的 window.__env 存在并且包含来自 settings.js 的数据 - 解决方案 100% 有效。如果您的代码无法到达窗口的子对象 - 这是一个单独的问题,值得在 StackOveflow 上提出专门的问题。也许你需要先声明类型:(window as any).__env
    • 很好的解释。关于 Vue 3 的注意事项 - Vue.use 不再可用;我使用了此处描述的提供/注入模式:stackoverflow.com/a/63101214/1186321
    【解决方案2】:

    你可以在公共目录中创建一个config.json文件,然后在main js中你可以获取它并加载配置文件。现在你的 dist 是用这个 config.json 创建的。

    fetch('/config.json').then(res => res.json()).then(config => {
         .......
    })
    

    【讨论】:

    • 非常简单实用,非常感谢!
    【解决方案3】:

    您是否事先知道完整的 IP 地址列表?如果是这样,您可以创建一个基于任何时间/位置逻辑返回正确 IP 的函数。

    否则,您可以尝试将设置文件移动到公共文件夹,添加到您的 .gitignore 文件中,确保在您的 public/index.html 中引用它。它现在将位于已编译的 Vue 应用程序之外,并且可以从 Vue 内部作为全局设置变量进行访问。

    所以你应该引用window.Settings而不是import {Settings} from '../../Settings'

    例如const ip = window.Settings.SERVER_IP;

    这样您可以直接编辑设置,而无需每次都重新编译。

    【讨论】:

      猜你喜欢
      • 2018-09-22
      • 1970-01-01
      • 2018-09-10
      • 1970-01-01
      • 1970-01-01
      • 2019-10-01
      • 1970-01-01
      • 2018-08-31
      • 1970-01-01
      相关资源
      最近更新 更多