我们如何将参数传递给已经构建的Vue JS应用程序?

时间:2020-09-11 14:11:37

标签: javascript vue.js webpack vuejs2

我们有一个Vue应用程序,可连接到Web服务并获取一些数据。 Web服务URL不同,具体取决于我们安装应用程序的位置。

我首先想到使用.env文件,但后来我意识到这些文件被注入到缩小的.js文件中。

main.js文件的情况下,将其保存在我的.env中非常方便:

Vue.prototype.ApiBaseUrl = process.env.VUE_APP_APIBASEURL
Vue.prototype.PrintDocsFolder = process.env.VUE_APP_PRINTDOCSFOLDER
Vue.prototype.TicketPrintWSocket = process.env.VUE_APP_TICKETPRINTWSOCKET   

该应用程序已构建。我不想为必须部署到的一百个位置中的每个位置构建应用程序。对于这种“官方”方法,我不确定。

Vue中是否有任何可以使用此配置的现成解决方案?基本上,我们需要在内置应用程序的根文件夹中有一个文件,并读取Vue.prototype.VARIABLES的值。

我们正在使用vue-cli 3。

3 个答案:

答案 0 :(得分:3)

就像其他人所说,您可以在运行时通过网络请求来执行此操作。如果您不知道要部署到哪里,则需要执行以下操作。

或者,您可以在基础结构和网络级别执行此操作。有时,对于A / B测试系统,就是这样。

或者,您可以在构建时执行此操作。对于静态资产(例如图像),我都做过这两个工作,有时您无法在运行时执行此操作,并且需要在构建时替换公共URL。对于网络请求方法,使用您托管的映射来获取静态json文件的可能性是肯定的。

您与使用.env文件的想法非常接近。

使用Vue CLI的构建时方法

在Vue CLI中,您可以通过在.env文件中指定前缀为VUE_APP_THE_API_URL的变量,然后像process.env.VUE_APP_THE_API_URL一样使用Webpack的DefinePlugin来免费使用。 https://www.codementor.io/@aswinmurugesh/deploying-a-django-application-in-windows-with-apache-and-mod_wsgi-uhl2xq09e

用法

在您的源代码中,使用process.env.VUE_APP_THE_API_URL和.env文件。在源代码中将您的API URL引用为process.env.VUE_APP_THE_API_URL,然后应按照计划使用.env文件在仅开发值和仅生产值之间进行切换。

仅用于生产的值将是虚假的且非常独特,因此当您找到+替换它时,它将是不同的。

查找+替换您使用的虚假API_URL

构建完用于生产的应用程序后,您将遍历一个包含要部署到的API URL的映射文件(json,js等)。

您将使用文件系统并查找+替换以根据需要多次复制应用程序,然后再通过S3快速,快速地进行部署。您可以在bash脚本中或使用{{ 1}}或node + execa

为什么您可能需要这样做

我必须在构建时执行此操作,因为由于webpack加载程序进行了优化,因此无法在运行时修改某些资产,因为它们会对公共路径等内容进行硬编码,因此速度更快。拥有数百个API / CDN网址,一遍又一遍地重建应用程序效率极低。

Vue CLI的操作方式(如果您不想node + fs

Vue CLI位于webpack的顶部,这是一种高级用例,因此您需要在VUE_APP_*内设置configureWebpack并将其指向vue.config.js文件。您想在Webpack或仅在构建过程中(bash,node,gulp等)进行此操作。

Vue CLI 3与主要的Webpack版本绑定在一起。现在是Webpack4。我将为您提供Webpack 4的答案,但是我认为他们正在更改Webpack v5中的插件名称。

定义插件

您想要的插件是Docs。只需执行上述步骤,即可使用所需选项手动设置require('webpack.config.js')。如果您不想将{ plugins: [ new DefinePlugin() ] }用作环境变量的前缀,则可以这样做。

答案 1 :(得分:1)

如果应该在每个位置AND YOU DON'T WANT TO LEAVE ANY TRACE OF THE WHOLE DATA上使用 100个位置部署应用程序,并且为每个位置just have to make 1 extra API to call to get the correct params使用不同的API /参数,除了变量的正确运行应用程序,我本可以将所有不同的参数亲自存储在一个中央数据库中,并创建一个单一的通用API ,该API可以决定将哪些参数提供给特定的部署。因此,在初始应用程序加载时,该应用程序将+-------------------+----------------------------+-----------------+--------------------+--+ | domainName | ApiBaseUrl | PrintDocsFolder | TicketPrintWSocket | | +-------------------+----------------------------+-----------------+--------------------+--+ | example.com | http://api-base-url-1.com/ | print-doc-1 | ticket-print-1 | | +-------------------+----------------------------+-----------------+--------------------+--+ | secondExample.com | http://api-base-url-2.com/ | print-doc-2 | ticket-print-2 | | +-------------------+----------------------------+-----------------+--------------------+--+ | thirdExample.com | http://api-base-url-3.com/ | print-doc-3 | ticket-print-3 | | +-------------------+----------------------------+-----------------+--------------------+--+ 。 (前提是每个部署都有一些唯一的标识符)。

例如,如果唯一标识符是在其上提供应用程序的域名。 您可以将这样的参数存储在数据库中:

current domain name

然后,在应用加载时,您可以进行axios(基于Promise的HTTP客户端)调用,并将const details = await axios.get('/common-api-with-all-the-details', { params: { domainName: location.hostname }); 传递为如下参数:

    IFNULL((
        SELECT School.SchoolID
        FROM School
        WHERE CONCAT(School.City, ' ', School.State) = Teacher.Location
    ),0) AS SchoolID

该通用API应该将域与db匹配,并相应地获取正确的记录。

优势:

  • 您无需重建应用程序或配置环境变量 单独地。
  • 您将始终控制要喂入的参数 到哪个特定部署。
  • 您可以更改/更新参数 飞行。
  • 您的整个数据存储区都不公开。

缺点:

  • 需要额外的服务器设置。
  • 在应用的初始加载时额外进行了1次API调用。

其他方法:

  • 通过将所有详细信息存储在数组中,可以避免使用数据库(如果数据集不是太大)。然后,在每个 COMMON API 调用中,您都可以将域名与数组进行匹配(lodash可以提供帮助),从而增加响应时间,降低复杂性并完全避免数据库设置。

  • 您可以使用无服务器架构来避免设置全新的服务器来托管您的 COMMON API ,Firebase Cloud功能或AWS Lambda具有大量免费层,可以覆盖相当数量的交通。

答案 2 :(得分:1)

只需在URL(例如本地JSON文件)中创建XMLHttpRequest,然后读取数据内容即可。

例如,您可以使用fetch(受95% browsers支持)从<projectroot>/config.json请求配置(每个部署位置可以唯一),然后设置全局属性结果:

// main.js

fetch('config.json')
  .then(res => res.json())
  .catch(error => {
    // ignore any errors
    console.warn(error)
    return {}
  })
  .then(config => {
    Vue.prototype.ApiBaseUrl = config.ApiBaseUrl
    Vue.prototype.PrintDocsFolder = config.PrintDocsFolder
    Vue.prototype.TicketPrintWSocket = config.TicketPrintWSocket

    // initialize app here
    new Vue(...)
  })

demo